dead-code-check

📁 cosmix/claude-loom 📅 1 day ago
1
总安装量
1
周安装量
#52134
全站排名
安装命令
npx skills add https://github.com/cosmix/claude-loom --skill dead-code-check

Agent 安装分布

codex 1

Skill 文档

Dead Code Detection

Overview

Dead code detection identifies code that exists in your codebase but is never called, imported, or used. This is a critical signal for incomplete feature integration: if you’ve written a function but nothing calls it, the feature isn’t wired up.

In loom plan verification, dead code checks serve two purposes:

  1. Wiring verification: Catch features that were implemented but never integrated
  2. Code quality: Identify cleanup opportunities and reduce maintenance burden

Dead code detection is especially valuable in integration-verify stages, where it acts as a final check that all implemented code is actually connected to the application.

When to Use

  • integration-verify stages: Final quality gate to catch orphaned code from all implementation stages
  • Per-stage acceptance criteria: Immediate feedback during implementation
  • Code cleanup: After refactoring or feature removal
  • Wiring validation: Combine with wiring checks to verify feature integration

If dead code exists after implementation, it typically means:

  • Feature wasn’t wired into the application (CLI command not registered, route not mounted, etc.)
  • Test code that isn’t being run
  • Leftover code from refactoring
  • Incomplete implementation

Language-Specific Configurations

Rust

Rust has built-in dead code detection via the compiler and clippy.

Recommended Approach: Use clippy with all warnings as errors

cargo clippy -- -D warnings

This catches dead code plus many other issues (unused imports, variables, etc.).

Dead-Code-Specific Check:

RUSTFLAGS="-D dead_code" cargo build 2>&1

Or target just dead code warnings:

cargo clippy -- -D dead_code

Fail Patterns:

  • warning: unused
  • dead_code
  • unused import
  • unused variable
  • never used
  • never constructed

Ignore Patterns:

  • Code with #[allow(dead_code)] attribute (intentional)
  • Test modules (#[cfg(test)])
  • Main entry points (fn main())
  • Public API items intended for external consumers
  • Items behind feature gates that aren’t enabled

YAML Template for Loom Plans:

# In acceptance criteria (recommended - catches more than just dead code)
acceptance:
  - "cargo clippy -- -D warnings"

# In truths (more specific dead code check)
truths:
  - "RUSTFLAGS=\"-D dead_code\" cargo build 2>&1 | grep -v 'Compiling' | grep -v 'Finished' | grep -q '^$'"

# Alternative: Check that clippy reports zero dead code warnings
truths:
  - "! cargo clippy -- -D dead_code 2>&1 | grep -q 'warning:'"

Working Directory Consideration:

Rust checks must run where Cargo.toml exists. If your project structure is:

.worktrees/my-stage/
└── loom/
    └── Cargo.toml

Set working_dir: "loom" in your stage configuration.


TypeScript

TypeScript dead code detection uses ts-prune, which finds unused exports.

Installation:

npm install --save-dev ts-prune
# or
bun add --dev ts-prune

Command:

npx ts-prune --error
# or
bunx ts-prune --error

The --error flag makes ts-prune exit with non-zero status if unused exports are found.

Fail Patterns:

  • used in module but not exported
  • unused export
  • Files with unused exports reported

Ignore Patterns:

  • index.ts files that re-export (barrel files)
  • Type-only exports used for type checking
  • Declaration files (.d.ts)
  • Public API exports intended for library consumers
  • Default exports in entry points

Configuration File (.tsprunerc):

{
  "ignore": "index.ts|types.d.ts"
}

YAML Template for Loom Plans:

# In acceptance criteria
acceptance:
  - "bunx ts-prune --error"

# In truths (verify zero unused exports)
truths:
  - "bunx ts-prune | wc -l | grep -q '^0$'"

# Alternative: Explicitly check for no unused exports
truths:
  - "! bunx ts-prune | grep -q 'used in module'"

Working Directory:

Run where package.json and tsconfig.json exist.


Python

Python dead code detection uses vulture, which finds unused code including functions, classes, variables, and imports.

Installation:

pip install vulture
# or
uv add --dev vulture

Command:

vulture src/ --min-confidence 80

The --min-confidence flag (0-100) controls false positive rate. Higher values mean fewer false positives but might miss some dead code.

Fail Patterns:

  • unused function
  • unused class
  • unused variable
  • unused import
  • unreachable code

Ignore Patterns:

  • __init__.py files
  • __all__ definitions (explicit public API)
  • Magic methods (__str__, __repr__, __eq__, etc.)
  • Test files and fixtures (often use dynamic discovery)
  • Setup.py and configuration files

Configuration File (pyproject.toml):

[tool.vulture]
min_confidence = 80
paths = ["src", "tests"]
ignore_names = ["setUp", "tearDown", "test_*"]

YAML Template for Loom Plans:

# In acceptance criteria
acceptance:
  - "vulture src/ --min-confidence 80"

# In truths (verify zero issues)
truths:
  - "vulture src/ --min-confidence 80 | wc -l | grep -q '^0$'"

# Alternative: Check for specific patterns
truths:
  - "! vulture src/ --min-confidence 80 | grep -q 'unused function'"
  - "! vulture src/ --min-confidence 80 | grep -q 'unused import'"

Working Directory:

Run where your Python source code is (usually project root or where pyproject.toml exists).


Go

Go dead code detection uses staticcheck, a comprehensive static analysis tool.

Installation:

go install honnef.co/go/tools/cmd/staticcheck@latest

Command:

staticcheck ./...

Relevant Checks:

  • U1000 – unused code (function, type, const, var)
  • U1001 – unused field

Fail Patterns:

  • is unused
  • field .* is unused
  • func .* is unused
  • U1000 check code
  • U1001 check code

Ignore Patterns:

  • Exported symbols in library packages (public API)
  • Interface method implementations (required by interface even if not directly called)
  • Functions assigned to variables for use via reflection
  • Code behind build tags not currently enabled

Configuration File (.staticcheck.conf):

checks = ["all", "-ST1000"]

YAML Template for Loom Plans:

# In acceptance criteria
acceptance:
  - "staticcheck ./..."

# In truths (verify no unused code)
truths:
  - "! staticcheck ./... | grep -q 'U1000'"
  - "! staticcheck ./... | grep -q 'is unused'"

# Alternative: Check exit code
truths:
  - "staticcheck ./... 2>&1 | wc -l | grep -q '^0$'"

Working Directory:

Run where go.mod exists (usually project root).


JavaScript

JavaScript dead code detection uses unimported, which finds unused files and unresolved imports.

Installation:

npm install --save-dev unimported
# or
bun add --dev unimported

Command:

npx unimported
# or
bunx unimported

Fail Patterns:

  • unresolved import
  • unused file
  • Files listed in output

Ignore Patterns:

  • Config files (.eslintrc.js, jest.config.js, etc.)
  • Entry points (index.js, main.js)
  • Dynamic imports using variables
  • Files imported via build tools (Webpack, Vite, etc.)

Configuration File (.unimportedrc.json):

{
  "entry": ["src/index.js", "src/server.js"],
  "extensions": [".js", ".jsx"],
  "ignorePatterns": ["**/node_modules/**", "**/*.config.js"]
}

YAML Template for Loom Plans:

# In acceptance criteria
acceptance:
  - "bunx unimported"

# In truths (verify no unused files)
truths:
  - "bunx unimported | wc -l | grep -q '^0$'"

# Alternative: Check for specific issues
truths:
  - "! bunx unimported | grep -q 'unused file'"
  - "! bunx unimported | grep -q 'unresolved import'"

Working Directory:

Run where package.json exists.


Handling False Positives

Dead code detection tools report false positives in these common scenarios:

1. Entry Points

Problem: Main functions, CLI handlers, API route handlers — nothing in your code calls them directly, but they’re invoked by the runtime/framework.

Solutions:

  • Rust: Entry points like fn main() are automatically excluded. For CLI subcommands, ensure they’re registered in the command enum.
  • TypeScript/JavaScript: Configure entry points in tool config (ts-prune, unimported)
  • Python: Use __all__ to mark public API, vulture respects it
  • Go: Exported functions in main package are excluded

2. Test Code

Problem: Test functions are called by the test runner, not by application code.

Solutions:

  • Rust: Code in #[cfg(test)] modules is automatically excluded
  • TypeScript/JavaScript: Exclude test directories in config
  • Python: Ignore patterns like test_*, setUp, tearDown
  • Go: Test files (*_test.go) are automatically handled

3. Framework Magic

Problem: Decorators, derive macros, annotations that use code implicitly.

Examples:

  • Rust: #[derive(Serialize)] uses private fields
  • Python: @dataclass, @property decorators
  • TypeScript: Decorators in frameworks like Angular, NestJS

Solutions:

  • Use language-specific ignore annotations
  • Configure tools to ignore decorated items
  • For Rust, use #[allow(dead_code)] on specific items

4. Public API / Library Code

Problem: Code exported for external consumers appears unused within the project.

Solutions:

  • Rust: Public items (pub) in library crates are excluded by default
  • TypeScript: Use .tsprunerc to ignore library entry points
  • Python: Define __all__ to mark public API
  • Go: Exported symbols (capitalized) in library packages are excluded

5. Feature Flags and Conditional Compilation

Problem: Code behind disabled feature flags or build tags.

Solutions:

  • Rust: Enable relevant features when running checks (--features=all)
  • Go: Use build tags to include all variants
  • Python/TypeScript/JavaScript: Comment or temporarily enable features during checks

6. Dynamic Loading and Reflection

Problem: Code loaded dynamically or invoked via reflection.

Solutions:

  • Document these cases clearly
  • Use tool-specific ignore comments
  • Consider integration tests that exercise dynamic code paths

Integration with Loom Plans

Placement in Plan Stages

Best Practice: integration-verify stage

Dead code checks are most valuable as a final quality gate:

stages:
  - id: integration-verify
    name: "Integration Verification"
    stage_type: integration-verify
    working_dir: "loom"
    acceptance:
      - "cargo test"
      - "cargo clippy -- -D warnings" # Includes dead code check
    truths:
      - "! cargo clippy -- -D dead_code 2>&1 | grep -q 'warning:'"

Per-Stage Checks:

Can also add to individual implementation stages for immediate feedback:

stages:
  - id: implement-auth
    name: "Implement Authentication"
    stage_type: standard
    working_dir: "loom"
    acceptance:
      - "cargo test auth"
      - "cargo clippy --package auth -- -D warnings"

Combining with Wiring Checks

Dead code detection is a strong signal but not definitive proof. Combine with wiring checks:

stages:
  - id: integration-verify
    name: "Integration Verification"
    stage_type: integration-verify
    working_dir: "loom"
    acceptance:
      - "cargo clippy -- -D warnings"
    wiring:
      - source: "src/main.rs"
        pattern: "Commands::NewCommand"
        description: "New command registered in CLI enum"
      - source: "src/commands/mod.rs"
        pattern: "pub mod new_command"
        description: "New command module exported"
    truths:
      - "loom new-command --help" # Functional verification

This triple-check approach (dead code + wiring + functional) catches integration issues reliably.

Working Directory and Paths

Critical Reminder: The working_dir field determines where commands execute.

Example project structure:

.worktrees/my-stage/
├── loom/
│   ├── Cargo.toml       <- Build tools expect this directory
│   └── src/
└── CLAUDE.md

Correct Configuration:

- id: verify
  working_dir: "loom" # Where Cargo.toml exists
  acceptance:
    - "cargo clippy -- -D warnings"
  truths:
    - "test -f src/new_feature.rs" # Relative to working_dir (loom/)

Wrong Configuration:

- id: verify
  working_dir: "." # Wrong - no Cargo.toml here
  acceptance:
    - "cargo clippy -- -D warnings" # FAILS: could not find Cargo.toml

Path Resolution Rule: ALL paths in acceptance, truths, artifacts, and wiring are relative to working_dir.


YAML Best Practices

Never Use Triple Backticks in YAML Descriptions

Wrong:

truths:
  - description: |
      Check for dead code like this:
      ```
      cargo clippy -- -D warnings
      ```
    command: "cargo clippy -- -D warnings"

This breaks YAML parsing.

Correct:

truths:
  - "cargo clippy -- -D warnings" # Check for dead code

Or with explicit description:

truths:
  - description: "Check for dead code using clippy with all warnings as errors"
    command: "cargo clippy -- -D warnings"

Silent Grep with -q

When using grep in truths, use -q (quiet) flag to suppress output:

truths:
  - "! cargo clippy -- -D dead_code 2>&1 | grep -q 'warning:'"

The ! negates the result (exit 0 if grep finds nothing).

Exit Code Checks

Tools that exit non-zero on finding issues can be used directly:

acceptance:
  - "cargo clippy -- -D warnings" # Exits non-zero on warnings
  - "staticcheck ./..." # Exits non-zero on issues
  - "bunx ts-prune --error" # Exits non-zero on unused exports

Tool Installation Checklist

Before adding dead code checks to your plan, ensure tools are available:

Rust:

  • Built-in: rustc, cargo
  • cargo install clippy (usually included with rustup)

TypeScript:

  • bun add --dev ts-prune or npm install --save-dev ts-prune

Python:

  • uv add --dev vulture or pip install vulture

Go:

  • go install honnef.co/go/tools/cmd/staticcheck@latest

JavaScript:

  • bun add --dev unimported or npm install --save-dev unimported

Add installation steps to your knowledge-bootstrap stage or document in project README.


Examples

Example 1: Rust Project with Comprehensive Checks

stages:
  - id: integration-verify
    name: "Integration Verification"
    stage_type: integration-verify
    working_dir: "loom"
    acceptance:
      - "cargo test"
      - "cargo clippy -- -D warnings"
      - "cargo build --release"
    truths:
      - "test -f src/commands/new_feature.rs"
      - "! cargo clippy -- -D dead_code 2>&1 | grep -q 'warning:'"
    wiring:
      - source: "src/main.rs"
        pattern: "Commands::NewFeature"
        description: "New feature command registered"

Example 2: TypeScript API with Dead Export Check

stages:
  - id: verify-api
    name: "Verify API Implementation"
    stage_type: integration-verify
    working_dir: "api"
    acceptance:
      - "bun test"
      - "bunx ts-prune --error"
      - "bun run typecheck"
    truths:
      - "bunx ts-prune | wc -l | grep -q '^0$'"
      - "curl -f http://localhost:3000/api/health"

Example 3: Python Data Pipeline

stages:
  - id: verify-pipeline
    name: "Verify Data Pipeline"
    stage_type: integration-verify
    working_dir: "pipeline"
    acceptance:
      - "pytest"
      - "vulture src/ --min-confidence 80"
      - "mypy src/"
    truths:
      - "! vulture src/ --min-confidence 80 | grep -q 'unused function'"
      - "test -f src/pipeline/transform.py"
    wiring:
      - source: "src/main.py"
        pattern: "from pipeline.transform import TransformStage"
        description: "Transform stage imported in main pipeline"

Example 4: Go Microservice

stages:
  - id: verify-service
    name: "Verify Microservice"
    stage_type: integration-verify
    working_dir: "service"
    acceptance:
      - "go test ./..."
      - "staticcheck ./..."
      - "go build"
    truths:
      - "! staticcheck ./... | grep -q 'U1000'"
      - "! staticcheck ./... | grep -q 'is unused'"
      - "test -f cmd/server/main.go"

Summary

Dead code detection is a powerful verification tool for loom plans:

  1. Catches incomplete wiring: Code exists but isn’t called = feature not integrated
  2. Language-specific tools: Rust (clippy), TypeScript (ts-prune), Python (vulture), Go (staticcheck), JavaScript (unimported)
  3. Best in integration-verify: Final quality gate after all implementation stages
  4. Combine with wiring checks: Dead code detection + wiring patterns + functional tests = comprehensive verification
  5. Handle false positives: Entry points, tests, framework magic — configure tools appropriately
  6. Working directory matters: Set working_dir to where build tools expect (where Cargo.toml, package.json, go.mod exist)

Use this skill when designing verification strategies for loom plans. Copy-paste the YAML templates and adapt tool configurations to your project’s structure.