Trace. Analyze. Prune. Ship only the code that runs.
Your Docker containers ship 3-5x more code than they execute. Every unused function is dead weight — increasing image size, build time, and attack surface.
Scalpel traces your application at the function level, builds a complete dependency graph (the Code Genome), and surgically removes code that never runs. The result: 60-80% smaller containers with dramatically fewer CVEs.
Before Scalpel After Scalpel
┌─────────────────┐ ┌─────────────────┐
│ node_modules/ │ │ node_modules/ │
│ ████████████ 285MB │ ███░░░░░░░ 64MB │
│ 148K functions │ │ 22K functions │
│ 17 CVEs │ │ 3 CVEs │
└─────────────────┘ └─────────────────┘
78% reduction — 14 CVEs eliminated
- Node.js 18+ (for JavaScript/TypeScript tracing)
- macOS ARM64 or Linux x86_64 for prebuilt binaries
- Or Rust 1.85+ to build from source
Beta notice (v0.1.0-beta.2): end-to-end CLI prune is STABLE for Python, JavaScript, and TypeScript — validated across real-world projects (click, requests, flask, httpx, starlette, zod, pino, typedoc) with a stub→verify-with-tests falsification gate. Six more languages (Go, Rust, Java, PHP, Ruby, C#) ship the static-only path as BETA — pipeline lands and unit tests pass, but full multi-project safety validation pending.
# 1. Install (prebuilt binary; see "Installation" below for options)
curl -fsSL https://raw.githubusercontent.com/radheradhe01/scalpel/main/install.sh | sh
# 2. Audit your project (read-only, no file changes)
cd /path/to/your/python/project
scalpel prune --lang python --mode audit
# 3. Stub unreachable functions, with auto-rollback if your tests break
scalpel prune --lang python --mode stub --yes \
--verify-with "python -m pytest -q"
# If pytest passes after stubbing → prune retained, .scalpel/ contains
# the manifest + xxh3-verified backup for manual rollback later.
# If pytest fails → scalpel auto-rolls back, source is byte-identical
# to pre-prune. Zero risk.
# 4. (optional) Manual rollback any time
scalpel rollback# JavaScript needs V8 coverage (npm test wraps `node --experimental-vm-modules`)
scalpel trace -- npm test
scalpel report .scalpel/coverage
scalpel prune .scalpel/coverage --mode audit
# TypeScript uses the static-only path (no coverage needed)
scalpel prune --lang typescript --mode audit
scalpel prune --lang typescript --mode stub --yes \
--verify-with "npm test"30 seconds to your first result. No configuration needed.
After scalpel report, you'll see something like:
📊 Dependency Waste Report
━━━━━━━━━━━━━━━━━━━━━━━━━
Total packages: 47
Used packages: 12 (25%)
Unused packages: 35 (75%)
Total functions: 8,412
Used functions: 1,203 (14%)
Prunable bytes: 18.2 MB
Grade: D (Score: 42/100)
1. TRACE 2. ANALYZE 3. PRUNE
Your tests run tree-sitter parses Remove unreachable
with tracing enabled source for all edges code surgically
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ V8 Coverage │ │ Static Call │ │ Audit mode │
│ sys.monitor │──merge──> │ Graph (AST) │──prune──> │ Stub mode │
│ go coverage │ │ 10 languages │ │ Aggressive │
└─────────────┘ └─────────────┘ └─────────────┘
Runtime + Static = Only code
(what ran) (what could run) that matters
Hybrid analysis: Runtime tracing provides high confidence ("this code definitely ran"). Static analysis provides completeness ("this code could theoretically run"). Code is only pruned when both agree it's unreachable. When in doubt, Scalpel keeps the code.
| Scalpel | Knip | DockerSlim | Snyk/Trivy | Tree-shaking | |
|---|---|---|---|---|---|
| Runtime tracing | Yes | No (static only) | Yes (syscall level) | No | No |
| Function-level pruning | Yes | No (reports only) | No (file/binary level) | No (reports only) | Yes (build-time) |
| Multi-language | 8 languages | JS/TS only | Language-agnostic | Language-agnostic | JS only |
| Sees dynamic imports | Yes (runtime) | No | Partially | No | No |
| SBOM generation | Yes (CycloneDX) | No | No | Yes | No |
| Container-aware | Yes | No | Yes | Yes | No |
| Actually removes code | Yes | No | Yes (files only) | No | Yes |
Scalpel is the first tool that combines runtime tracing with static analysis to surgically remove unused code at the function level — across 8 languages.
| Language | Status | Min Version | Pipeline | Multi-project Safety Gate |
|---|---|---|---|---|
| Python | Stable | 3.9+ | static + coverage.py | 6-project safety test (click, flask, httpx, requests, starlette, pydantic) |
| JavaScript | Stable | Node.js 18 LTS | V8 coverage + static | node_modules-based projects |
| TypeScript | Stable | Node.js 18 LTS | static-only (.ts/.tsx) |
zod / pino / typedoc audit + typedoc stub→verify mocha cycle |
| Go | Beta | 1.21+ | static-only (.go) |
cobra audit (0 prunable) |
| Rust | Beta | 1.68+ | static-only (.rs) |
scalpel itself (0 prunable, dogfood) |
| Java | Beta | 11+ | static-only (.java) |
unit + 2 fixture tests |
| PHP | Beta | 8.1+ | static-only (.php) |
unit tests |
| Ruby | Beta | 2.5+ | static-only (.rb) |
unit tests |
| C# | Beta | .NET 6+ | static-only (.cs) |
unit tests |
Stable = end-to-end CLI prune validated against real projects with a stub→test cycle gate. Stubbing breaks tests → auto-rollback. Beta = pipeline lands and unit tests pass; multi-project safety validation pending.
| Command | Description |
|---|---|
scalpel trace |
Trace a command and collect runtime coverage |
scalpel analyze |
Run static analysis on source code |
scalpel report |
Generate a waste report from coverage data |
scalpel prune |
Prune unused code (audit / stub / aggressive) |
scalpel score |
Compute dependency health score (0-100, A-F grade) |
scalpel dockerize |
Full pipeline: trace → analyze → prune → rebuild Docker image |
scalpel serve |
Launch interactive Code Genome visualization |
scalpel sbom |
Generate Software Bill of Materials (CycloneDX / SPDX) |
scalpel diff |
Compare two genome exports |
scalpel ci |
CI gate: score + regression detection |
scalpel rollback |
Undo the last pruning operation |
scalpel export |
Export genome as JSON |
Scalpel is conservative by default. A false positive (pruning used code) breaks production. A false negative (keeping unused code) is merely wasteful. Scalpel chooses the safe side:
- Error handlers (try/catch/finally), signal handlers, and shutdown hooks are never pruned
- Circular dependencies are treated atomically — if any function in a cycle is reachable, all are kept
- Side-effect modules are kept if any part of the module is used
- Re-export chains are fully resolved before marking exports as prunable
- Three-mode pruning:
audit(report only) →stub(error stubs) →aggressive(delete) — you choose the risk level - Automatic backup with one-command
scalpel rollback
| Feature | Linux | macOS | Windows |
|---|---|---|---|
| Coverage-based tracing | Yes | Yes | Yes |
| Real-time tracing (IPC) | Yes | Yes | Auto-fallback to coverage |
| Static analysis | Yes | Yes | Yes |
| Pruning | Yes | Yes | Yes |
| Visualization | Yes | Yes | Yes |
Architectures: x86_64, ARM64 (Apple Silicon)
# .github/workflows/scalpel.yml
- uses: radheradhe01/scalpel@main
with:
language: node
threshold: 50
fail-on-regression: trueOutputs: score, grade, waste-percentage, prunable-bytes. Uploads genome export as artifact for diff tracking across commits.
scalpel score produces a 0-100 score with letter grades:
| Grade | Score | Meaning |
|---|---|---|
| A | 90-100 | Minimal waste. Dependencies are lean. |
| B | 75-89 | Some unused code. Overall healthy. |
| C | 60-74 | Significant dead code. Consider pruning. |
| D | 40-59 | Majority of dependencies unused. |
| F | 0-39 | Critical waste. Most code never executes. |
# Default: installs to /usr/local/bin (uses sudo if needed)
curl -fsSL https://raw.githubusercontent.com/radheradhe01/scalpel/main/install.sh | sh
# Or install to a user-writable directory (no sudo needed):
curl -fsSL https://raw.githubusercontent.com/radheradhe01/scalpel/main/install.sh \
| SCALPEL_INSTALL_DIR=$HOME/.local/bin sh
# Then add $HOME/.local/bin to your PATH.Supported platforms: Linux x86_64, macOS ARM64 (Apple Silicon), Windows x86_64. The installer verifies SHA256 checksums.
git clone https://github.com/radheradhe01/scalpel.git
cd scalpel
cargo install --path crates/scalpel-cli
# Or directly from the git repo:
cargo install --git https://github.com/radheradhe01/scalpel scalpel-cliScalpel includes an MCP server that lets AI coding assistants (Claude Code, Cursor, Windsurf) query your codebase's dependency graph:
// .mcp.json — add to your project root
{
"mcpServers": {
"scalpel": {
"command": "scalpel",
"args": ["mcp", "--genome", ".scalpel/genome-export.json", "--project-root", "."]
}
}
}Generate the genome first: scalpel export .scalpel/coverage -o .scalpel/genome-export.json
12 MCP tools for AI agents: search_genome, get_context, trace_call_chain, get_dependencies, get_dependents, get_function_profile, get_hotspots, get_unused_code, get_health_score, get_genome_summary, diff_genomes, reload_genome.
| Problem | Solution |
|---|---|
parsing coverage error |
Run scalpel trace -- npm test first to generate coverage data |
node_modules not found |
Run npm install in your project directory |
| Empty report (0 functions) | Ensure your tests actually import and exercise your dependencies |
| MCP server not connecting | Check .mcp.json paths are absolute or relative to project root |
| Command exited with non-zero code | Your test command failed — run it standalone first to debug |
Language Probes ──→ scalpel-tracer ──→ scalpel-core (Code Genome)
(JS/Py/Go/etc) (event ingestion) ↑ ↓
scalpel-analyze scalpel-prune
(tree-sitter AST) (surgical removal)
↓
Pruned Container + SBOM
8-crate Cargo workspace: scalpel-proto → scalpel-alloc → scalpel-ipc → scalpel-core → scalpel-tracer → scalpel-analyze → scalpel-prune → scalpel-cli
Contributions welcome! See CONTRIBUTING.md for guidelines.
Good first issues are labeled and mentored — check the issues page.
# Development
cargo build
cargo test --all
cargo clippy --all -- -D warnings
cargo fmt --all -- --checkLicensed under either of Apache License, Version 2.0 or MIT License at your option.