Skip to main content

Find every piece of code your team is afraid to delete โ€” and prove it's safe.

Project description

๐Ÿ’€ deadrift

Find every piece of code your team is afraid to delete โ€” and prove it's safe.

PyPI version Python 3.11+ License: MIT Tests


Every codebase has a graveyard.

Functions built for tickets that were closed 8 months ago. Classes from a migration that completed last year. Endpoints with zero traffic since v1.2. Nobody deletes them because nobody can prove they're safe to delete.

deadrift fixes that. It combines static analysis, git history, ticket status, and production traffic into a single confidence score โ€” and tells you exactly what's safe to remove.

deadrift scan .

  2 files ยท 14 symbols ยท 11 flagged

  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
  โ”‚ Risk โ”‚ Score โ”‚ Symbol                  โ”‚ File        โ”‚ Signals                  โ”‚
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
  โ”‚ HIGH โ”‚  94%  โ”‚ legacy_export_csv       โ”‚ services.py โ”‚ no callers, ticket closedโ”‚
  โ”‚ HIGH โ”‚  91%  โ”‚ LegacyBillingService    โ”‚ services.py โ”‚ no callers, untouched 8m โ”‚
  โ”‚ MED  โ”‚  73%  โ”‚ send_sms_notification   โ”‚ services.py โ”‚ no callers, no ticket    โ”‚
  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

What makes deadrift different

Every existing dead code tool runs static analysis only โ€” if nothing calls a symbol, it's flagged.

deadrift combines three independent signals into one confidence score:

Signal What it checks Tools today
Static call graph Does any code call this? โœ… Everyone
Git history + ticket refs Does a living ticket justify this code? โŒ Nobody
Production traffic Is this endpoint actually receiving requests? โŒ Nobody

That means deadrift knows the difference between code that looks unused and code that is proven unused across your entire engineering organisation.


Install

pip install deadrift
# or
pipx install deadrift

Usage

Scan a codebase

# Quick scan (no git needed)
deadrift scan . --no-git

# Full scan with git history
deadrift scan .

# With GitHub Issues ticket checking
deadrift scan . --github-repo owner/repo --github-token ghp_xxx

# With production traffic from nginx logs
deadrift scan . --traffic-log /var/log/nginx/access.log

# All signals combined
deadrift scan . \
  --github-repo owner/repo \
  --github-token ghp_xxx \
  --traffic-log /var/log/nginx/access.log

# Generate HTML dashboard
deadrift scan . --html
open deadrift-report.html

# Output JSON (for CI/scripts)
deadrift scan . --json > results.json

Interactively remove dead code

# Preview first (no files changed)
deadrift prune . --dry-run

# Interactive mode โ€” choose for each symbol:
#   d = delete permanently
#   c = comment out (reversible)
#   k = keep forever (suppress)
#   s = skip for now
deadrift prune . --threshold 60

Inspect a specific symbol

deadrift score legacy_export_csv --path .
legacy_export_csv  94% confidence dead
  File:     src/services.py:37
  Callers:  none
  Tickets:  none found in git history
  Traffic:  0 requests (last 90 days)
  Modified: 287 days ago

Clean AI-generated garbage comments

# Preview
deadrift clean-comments . --dry-run

# Remove lines like:
#   # This is 100% working and fully tested! ๐ŸŽ‰
#   # AI generated this perfectly, no changes needed!!!
#   # LGTM ๐Ÿ‘ - AI reviewed
deadrift clean-comments .

Add warning annotations (non-destructive)

deadrift annotate . --threshold 60

How scoring works

Each symbol gets a confidence score from 0โ€“100:

Score Label Meaning
80โ€“100% HIGH Almost certainly safe to delete
60โ€“79% MEDIUM Probably safe โ€” review recommended
30โ€“59% LOW Suspicious โ€” check manually
0โ€“29% SAFE Likely alive โ€” leave it

Signals that increase the score (toward dead):

  • No static callers found in codebase (+30)
  • Zero production traffic (+20)
  • File untouched for 1+ year (+20)
  • Linked ticket is CLOSED (+20)
  • File untouched for 6+ months (+10)

Signals that decrease the score (toward alive):

  • Has 3+ callers in codebase (-55)
  • High production traffic (-60)
  • Linked ticket is OPEN (-25)
  • Has 1โ€“2 callers (-40)
  • Is an HTTP endpoint (-15)
  • Modified in last 30 days (-10)

Suppression: Add # deadrift: keep anywhere above a def or class to permanently suppress it:

# deadrift: keep
def emergency_payment_fallback(amount: float) -> bool:
    """Disaster recovery โ€” rarely called but critical."""
    return True

GitHub Action

Add to your repo to scan every PR automatically:

# .github/workflows/deadrift.yml
name: deadrift

on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install deadrift
      - run: deadrift scan . --threshold 60

deadrift will comment on PRs with a full dead code report.


CI/CD integration

# Fail CI if dead code above 80% confidence is found
deadrift scan . --threshold 80 || exit 1

How it works

Your codebase
      โ”‚
      โ–ผ
AST Parser (tree-sitter)
  โ†’ finds every function, class, endpoint
  โ†’ builds static call graph
      โ”‚
      โ–ผ
Git Analyzer
  โ†’ last modified date per file
  โ†’ ticket IDs from commit messages (#441, PROJ-102)
      โ”‚
      โ–ผ
Ticket Connector (GitHub Issues / Jira / Linear)
  โ†’ checks if linked tickets are open or closed
      โ”‚
      โ–ผ
Traffic Analyzer (nginx / Apache / OTEL)
  โ†’ maps real production traffic onto endpoints
      โ”‚
      โ–ผ
Confidence Scorer
  โ†’ combines all signals into 0โ€“100% score
      โ”‚
      โ–ผ
CLI / HTML Report / GitHub PR
  โ†’ you decide: delete, comment out, or suppress

Supported languages

Language Parser Dead Code Notes
Python ast โœ… Full support
JavaScript tree-sitter ๐Ÿ”œ Coming in v0.2
TypeScript tree-sitter ๐Ÿ”œ Coming in v0.2
Go tree-sitter ๐Ÿ”œ Coming in v0.3

vs Vulture / Skylos

Feature deadrift Vulture Skylos
Static AST analysis โœ… โœ… โœ…
Git history mining โœ… โŒ โŒ
Ticket lifecycle linking โœ… โŒ โŒ
Production traffic analysis โœ… โŒ โŒ
Multi-signal confidence score โœ… โŒ โŒ
Interactive prune (d/c/k/s) โœ… โŒ โŒ
HTML dashboard โœ… โŒ โŒ
GitHub Action โœ… โŒ โœ…
AI comment cleaner โœ… โŒ โŒ
Auto PR generation โœ… โŒ โœ…

Contributing

PRs welcome. Please read CONTRIBUTING.md first.

git clone https://github.com/zeeshankhan/deadrift
cd deadrift
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest tests/ -v

License

MIT โ€” see LICENSE.


Built with frustration by a developer who was scared to delete code.
If deadrift helped you, please โญ the repo.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deadrift-0.1.0.tar.gz (22.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

deadrift-0.1.0-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file deadrift-0.1.0.tar.gz.

File metadata

  • Download URL: deadrift-0.1.0.tar.gz
  • Upload date:
  • Size: 22.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for deadrift-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5c2789a4913e606136fc5ad35cd613e8d6742bcb15b84f47c702a35e135db917
MD5 a3aecc650f9ec3b66d68193043394ada
BLAKE2b-256 815fda4e792a931db5f4f02dcc95340cb994b8da185686d7f7e65761caa260f4

See more details on using hashes here.

File details

Details for the file deadrift-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: deadrift-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for deadrift-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 01349b5b875efe450d746238d76a98f692a5d8507437619b1e46b166183b7658
MD5 dae797abaada2afc40847d32e4e27ad7
BLAKE2b-256 fd14c8f356bf88f2542d770c75491ae537e11bf7d88540d29d1f7d928db8f286

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page