Claude Code Plugins

Community-maintained marketplace

Feedback
1
0

Detects backward-incompatible changes to public APIs, function signatures, endpoints, and data schemas before they break production. Suggests migration paths.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name breaking-change-detector
description Detects backward-incompatible changes to public APIs, function signatures, endpoints, and data schemas before they break production. Suggests migration paths.

Breaking Change Detector Skill

Purpose: Catch breaking changes early, not after customers complain.

Trigger Words: API, endpoint, route, public, schema, model, interface, contract, signature, rename, remove, delete


Quick Decision: Is This Breaking?

def is_breaking_change(change: dict) -> tuple[bool, str]:
    """Fast breaking change evaluation."""

    breaking_patterns = {
        # Method signatures
        "removed_parameter": True,
        "renamed_parameter": True,
        "changed_parameter_type": True,
        "removed_method": True,
        "renamed_method": True,

        # API endpoints
        "removed_endpoint": True,
        "renamed_endpoint": True,
        "changed_response_format": True,
        "removed_response_field": True,

        # Data models
        "removed_field": True,
        "renamed_field": True,
        "changed_field_type": True,
        "made_required": True,

        # Return types
        "changed_return_type": True,
    }

    # Safe changes (backward compatible)
    safe_patterns = {
        "added_parameter_with_default": False,
        "added_optional_field": False,
        "added_endpoint": False,
        "added_response_field": False,
        "deprecated_but_kept": False,
    }

    change_type = change.get("type")
    return breaking_patterns.get(change_type, False), change_type

Common Breaking Changes (With Fixes)

1. Removed Function Parameter ❌ BREAKING

# BEFORE (v1.0)
def process_payment(amount, currency, user_id):
    pass

# AFTER (v2.0) - BREAKS EXISTING CODE
def process_payment(amount, user_id):  # Removed currency!
    pass

# ✅ FIX: Keep parameter with default
def process_payment(amount, user_id, currency="USD"):
    """
    Args:
        currency: Deprecated in v2.0, always uses USD
    """
    pass

Migration Path: Add default value, deprecate, document.


2. Renamed Function/Method ❌ BREAKING

# BEFORE
def getUserProfile(user_id):
    pass

# AFTER - BREAKS CALLS
def get_user_profile(user_id):  # Renamed!
    pass

# ✅ FIX: Keep both, deprecate old
def get_user_profile(user_id):
    """Get user profile (v2.0+ naming)."""
    pass

def getUserProfile(user_id):
    """Deprecated: Use get_user_profile() instead."""
    warnings.warn("getUserProfile is deprecated, use get_user_profile", DeprecationWarning)
    return get_user_profile(user_id)

Migration Path: Alias old name → new name, add deprecation warning.


3. Changed Response Format ❌ BREAKING

# BEFORE - Returns dict
@app.route("/api/user/<id>")
def get_user(id):
    return {"id": id, "name": "Alice", "email": "alice@example.com"}

# AFTER - Returns list - BREAKS CLIENTS!
@app.route("/api/user/<id>")
def get_user(id):
    return [{"id": id, "name": "Alice", "email": "alice@example.com"}]

# ✅ FIX: Keep format, add new endpoint
@app.route("/api/v2/user/<id>")  # New version
def get_user_v2(id):
    return [{"id": id, "name": "Alice"}]

@app.route("/api/user/<id>")  # Keep v1
def get_user(id):
    return {"id": id, "name": "Alice", "email": "alice@example.com"}

Migration Path: Version the API (v1, v2), keep old version alive.


4. Removed Endpoint ❌ BREAKING

# BEFORE
@app.route("/users")
def get_users():
    pass

# AFTER - REMOVED! Breaks clients.
# (endpoint deleted)

# ✅ FIX: Redirect to new endpoint
@app.route("/users")
def get_users():
    """Deprecated: Use /api/v2/accounts instead."""
    return redirect("/api/v2/accounts", code=301)  # Permanent redirect

Migration Path: Keep endpoint, redirect with 301, document deprecation.


5. Changed Required Fields ❌ BREAKING

# BEFORE - email optional
class User:
    def __init__(self, name, email=None):
        self.name = name
        self.email = email

# AFTER - email required! Breaks existing code.
class User:
    def __init__(self, name, email):  # No default!
        self.name = name
        self.email = email

# ✅ FIX: Keep optional, validate separately
class User:
    def __init__(self, name, email=None):
        self.name = name
        self.email = email

    def validate(self):
        """Validate required fields."""
        if not self.email:
            raise ValueError("Email is required (new in v2.0)")

Migration Path: Keep optional in constructor, add validation method.


6. Removed Response Field ❌ BREAKING

# BEFORE
{
    "id": 123,
    "name": "Alice",
    "age": 30,
    "email": "alice@example.com"
}

# AFTER - Removed age! Breaks clients expecting it.
{
    "id": 123,
    "name": "Alice",
    "email": "alice@example.com"
}

# ✅ FIX: Keep field with null/default
{
    "id": 123,
    "name": "Alice",
    "age": null,  # Deprecated, always null in v2.0
    "email": "alice@example.com"
}

Migration Path: Keep field with null, document deprecation.


Non-Breaking Changes ✅ (Safe)

1. Added Optional Parameter

# BEFORE
def process_payment(amount):
    pass

# AFTER - Safe! Has default
def process_payment(amount, currency="USD"):
    pass

# Old calls still work:
process_payment(100)  # ✅ Works

2. Added Response Field

# BEFORE
{"id": 123, "name": "Alice"}

# AFTER - Safe! Added field
{"id": 123, "name": "Alice", "created_at": "2025-10-30"}

# Old clients ignore new field: ✅ Works

3. Added New Endpoint

# New endpoint added
@app.route("/api/v2/users")
def get_users_v2():
    pass

# Old endpoint unchanged: ✅ Safe

Detection Strategy

Automatic Checks

  1. Function signatures: Compare old vs new parameters, types, names
  2. API routes: Check for removed/renamed endpoints
  3. Data schemas: Validate field additions/removals/renames
  4. Return types: Detect type changes

When to Run

  • ✅ Before committing changes to public APIs
  • ✅ During code review
  • ✅ Before releasing new version

Output Format

## Breaking Change Report

**Status**: [✅ NO BREAKING CHANGES | ⚠️ BREAKING CHANGES DETECTED]

---

### Breaking Changes: 2

1. **[CRITICAL] Removed endpoint: GET /users**
   - **Impact**: External API clients will get 404
   - **File**: api/routes.py:45
   - **Fix**:
     ```python
     # Keep endpoint, redirect to new one
     @app.route("/users")
     def get_users():
         return redirect("/api/v2/accounts", code=301)
     ```
   - **Migration**: Add to CHANGELOG.md, notify users

2. **[HIGH] Renamed parameter: currency → currency_code**
   - **Impact**: Existing function calls will fail
   - **File**: payments.py:23
   - **Fix**:
     ```python
     # Accept both, deprecate old name
     def process_payment(amount, currency_code=None, currency=None):
         # Support old name temporarily
         if currency is not None:
             warnings.warn("currency is deprecated, use currency_code")
             currency_code = currency
     ```

---

### Safe Changes: 1

1. **[SAFE] Added optional parameter: timeout (default=30)**
   - **File**: api_client.py:12
   - **Impact**: None, backward compatible

---

**Recommendation**:
1. Fix 2 breaking changes before merge
2. Document breaking changes in CHANGELOG.md
3. Bump major version (v1.x → v2.0) per semver
4. Notify API consumers 2 weeks before release

Integration with Workflow

# Automatic trigger when modifying APIs
/lazy code "rename /users endpoint to /accounts"

→ breaking-change-detector triggers
→ Detects: Endpoint rename is breaking
→ Suggests: Keep /users, redirect to /accounts
→ Developer applies fix
→ Re-check: ✅ Backward compatible

# Before PR
/lazy review US-3.4

→ breaking-change-detector runs
→ Checks all API changes in PR
→ Reports breaking changes
→ PR blocked if breaking without migration plan

Version Bumping Guide

# Semantic versioning
Given version: MAJOR.MINOR.PATCH

# Breaking change detected → Bump MAJOR
1.2.3 → 2.0.0

# New feature (backward compatible) → Bump MINOR
1.2.3 → 1.3.0

# Bug fix (backward compatible) → Bump PATCH
1.2.3 → 1.2.4

What This Skill Does NOT Do

❌ Catch internal/private API changes (only public APIs) ❌ Test runtime compatibility (use integration tests) ❌ Manage database migrations (separate tool) ❌ Generate full migration scripts

DOES: Detect public API breaking changes, suggest fixes, enforce versioning.


Configuration

# Strict mode: flag all changes (even safe ones)
export LAZYDEV_BREAKING_STRICT=1

# Disable breaking change detection
export LAZYDEV_DISABLE_BREAKING_DETECTOR=1

# Check only specific types
export LAZYDEV_BREAKING_CHECK="endpoints,schemas"

Version: 1.0.0 Follows: Semantic Versioning 2.0.0 Speed: <3 seconds for typical PR