This skill should be used when the user asks about "code duplication", "jscpd", "DRY principle", "duplicate code", "clone detection", "code consolidation", or needs guidance on when and how to consolidate duplicate Go code.
Detects duplicate Go code patterns and suggests consolidation strategies like helper functions, interfaces, or generics. Use when users mention code duplication, DRY principle, or need guidance on when to share vs duplicate code.
/plugin marketplace add dkoosis/cc-plugins/plugin install go-dedup@cc-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Strategies for identifying and consolidating duplicate code in Go codebases.
jscpd detects copy-pasted code blocks. Not all duplication is bad - the goal is intentional, documented decisions about when to share vs duplicate.
20 lines duplicated
Use when: Identical code blocks with different inputs.
// handlers/user.go
func CreateUser(w http.ResponseWriter, r *http.Request) {
var req UserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
if err := validate(req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// ... user-specific logic
}
// handlers/order.go
func CreateOrder(w http.ResponseWriter, r *http.Request) {
var req OrderRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
if err := validate(req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// ... order-specific logic
}
// handlers/helpers.go
func decodeAndValidate[T any](r *http.Request, validate func(T) error) (T, error) {
var req T
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return req, fmt.Errorf("invalid JSON: %w", err)
}
if err := validate(req); err != nil {
return req, err
}
return req, nil
}
// handlers/user.go
func CreateUser(w http.ResponseWriter, r *http.Request) {
req, err := decodeAndValidate[UserRequest](r, validateUser)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// ... user-specific logic
}
Use when: Same operations on different types.
func SaveUser(db *sql.DB, u *User) error {
query := "INSERT INTO users (name, email) VALUES (?, ?)"
_, err := db.Exec(query, u.Name, u.Email)
return err
}
func SaveOrder(db *sql.DB, o *Order) error {
query := "INSERT INTO orders (product, quantity) VALUES (?, ?)"
_, err := db.Exec(query, o.Product, o.Quantity)
return err
}
type Saveable interface {
InsertQuery() string
InsertArgs() []any
}
func Save(db *sql.DB, item Saveable) error {
_, err := db.Exec(item.InsertQuery(), item.InsertArgs()...)
return err
}
func (u *User) InsertQuery() string { return "INSERT INTO users (name, email) VALUES (?, ?)" }
func (u *User) InsertArgs() []any { return []any{u.Name, u.Email} }
Use when: Same algorithm, different types, want compile-time safety.
func FilterUsers(users []User, pred func(User) bool) []User {
var result []User
for _, u := range users {
if pred(u) {
result = append(result, u)
}
}
return result
}
func FilterOrders(orders []Order, pred func(Order) bool) []Order {
var result []Order
for _, o := range orders {
if pred(o) {
result = append(result, o)
}
}
return result
}
func Filter[T any](items []T, pred func(T) bool) []T {
var result []T
for _, item := range items {
if pred(item) {
result = append(result, item)
}
}
return result
}
Use when: Similar code with many optional variations.
// Multiple functions with slight variations
func NewClientWithTimeout(url string, timeout time.Duration) *Client
func NewClientWithRetry(url string, retries int) *Client
func NewClientWithTimeoutAndRetry(url string, timeout time.Duration, retries int) *Client
type ClientOption func(*Client)
func WithTimeout(d time.Duration) ClientOption {
return func(c *Client) { c.timeout = d }
}
func WithRetry(n int) ClientOption {
return func(c *Client) { c.retries = n }
}
func NewClient(url string, opts ...ClientOption) *Client {
c := &Client{url: url, timeout: 30 * time.Second}
for _, opt := range opts {
opt(c)
}
return c
}
Use when: Consolidation would be worse than duplication.
// NOTE: This validation logic is intentionally duplicated from orders/validate.go
// User validation and order validation share structure now but will diverge
// as we add user-specific rules (e.g., email format, age verification).
// See ADR-015 for discussion.
func validateUser(u *User) error {
if u.Name == "" {
return errors.New("name required")
}
// ...
}
| Duplication Scope | Placement |
|---|---|
| Within same package | unexported helper in same file |
| Across sibling packages | shared parent package |
| Across domains | internal/common/ or domain-specific internal/shared/ |
| Across repositories | Consider shared module |
| Metric | Good | Warning |
|---|---|---|
| Clone count | <5 | >15 |
| Clone % | <2% | >5% |
| Largest clone | <30 lines | >50 lines |
After consolidation:
# Tests must pass
go test ./...
# Duplication reduced
jscpd --format go ./...
# No new lint issues
golangci-lint run ./...
This skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.