Dead Code Analysis

ctxo find_dead_code
vs Manual Analysis

Same codebase. Same model. Same question.
One uses the dependency graph. One doesn't.

What Was the Task
Find All Dead Code in a Real-World Codebase
A production backend service with ~2,400 symbols across API endpoints, sync services, infrastructure helpers, and background jobs. The goal: identify every unreachable symbol, unused export, and dead class - then separate true dead code from framework false positives.

Codebase Profile

Multi-language 2,382 symbols Claude Opus 4.6

Includes API layer with minimal endpoints, DI-registered services, CLI commands (Spectre.Console), background sync jobs, and repository pattern with interface-based dispatch.

Two Approaches

With ctxo: Single find_dead_code call uses the pre-built dependency graph to analyze all 2,382 symbols at once.

Without ctxo: Manual static analysis using Grep + Read, scanning files one at a time across 8 rounds of pattern matching.

Performance Metrics
Head-to-Head Comparison
Both approaches used the same Claude Opus 4.6 model on the same codebase. The only difference: ctxo's dependency graph vs raw file scanning.
Metric With ctxo Without ctxo Delta
Iterations (rounds)188x fewer
Tool calls5~357x fewer
Input tokens~30,000~50,00040% less
Output tokens~3,000~6,00050% less
Execution time~35 seconds~7 minutes12x faster
Symbols analyzed2,382 (full graph)~200 (sampled)12x coverage
Confirmed dead code2 classes + 8 suspicious4 classes + 4 fields + 12 countersFull graph coverage
False positive triage203 categorized by typeNot applicableAuto-classified
Result Quality
What Each Approach Found
Breadth vs depth. The dependency graph sees the whole forest; manual analysis inspects individual trees.

ctxo find_dead_code

  • Full graph traversal: 2,382 symbols, 1,723 reachable
  • 2 confirmed dead classes (CommandModel, AuditEntry)
  • 8 suspicious symbols flagged for investigation
  • 203 unused exports auto-categorized (DI, reflection, CLI, tests)
  • Zero orphan files detected
  • False positive categories explained (why they appear unused)

Manual Analysis

  • 4 dead classes found (CommandModel, AuditEntry, StringExtensions, ApiErrorMapping)
  • 4 unused fields/constants identified
  • 12 never-incremented counters across 4 files (misleading logs)
  • 1 commented-out code block
  • 1 duplicate method spotted (ComputeSha256)
  • 1 TODO flagged for deletion found

Verdict: Complementary Strengths

ctxo provides unmatched breadth - it analyzed every symbol in the codebase and correctly classified 203 framework false positives that manual analysis never even encountered. It found the same 2 core dead classes instantly.

Manual analysis found more granular depth - field-level dead code, never-incremented counters, and behavioral patterns that require reading individual lines of code. It also found 2 additional dead classes (StringExtensions, ApiErrorMapping) that ctxo flagged but didn't highlight.

The ideal workflow: Start with ctxo for full coverage and false positive triage, then do targeted manual deep-dives on suspicious areas. This gives you both breadth AND depth in a fraction of the time.

Live Comparison
Side-by-Side: Claude Code Sessions
Two real conversations running the same dead code analysis. Left uses ctxo's dependency graph. Right does it manually.
With ctxo ~35 seconds
U
Find me dead codes in the codebase.
C
I'll use ctxo's find_dead_code to analyze the full dependency graph.
find_dead_code (ctxo)
scope: "src/SampleApp/"
Result
totalSymbols: 2,382 | reachable: 1,723 | unusedExports: 203 | orphanFiles: 0
C
Analysis complete. Here's what the dependency graph reveals:
Confirmed Dead Code
  • CommandModel - API/SampleApp.cs - zero importers
  • AuditEntry - Events directory - zero importers
203 Unused Exports (False Positives)
  • API Endpoints - runtime reflection (MapGroup)
  • CLI Commands - Spectre.Console framework
  • DI Registrations - builder.Services.Add*()
  • Interface impls - dispatched via interface
  • Test classes - test runner discovery
8 Suspicious (Investigate)
  • SessionIdentity - unused model class
  • SetSecureConnectionString - leftover utility
  • DecryptAssetFile / EncryptAssetFile - legacy
  • GetDecryptedCertHash - possibly unused
  • ReadEncryptedConfigValue - superseded?
  • UpdateStatusAsync - check API calls
Without ctxo (Manual) ~7 minutes
U
Find me dead codes. DO NOT USE CTXO MCP TOOLS
C
I'll perform manual static analysis using Grep and Read tools.
Agent (Explore)
Scan for dead code patterns: unused private methods, commented code, [Obsolete]...
Round 1 Result
Found: ReadOptions unused field in AuthorizationEndpointFilter
Round 2 of 8
Grep x3
private fields, commented-out code, [Obsolete]
Found
Commented-out counters in CalendarCollector
Round 3 of 8
Grep x3
Verify ReadOptions, check StatusDeleted/StatusInactive usage
Confirmed
StatusDeleted, StatusInactive - never referenced
Round 4 of 8
Read x1, Grep x4
Check counter increments in sync files
Found
totalThrottleCount, totalGatewayErrorCount, totalRetryCount - never incremented in 4 files
Rounds 5-8
Grep x18, Read x3
Deep verification, class scanning, CommandModel, StringExtensions, ApiErrorMapping, AuditEntry...
C
Analysis complete. After 8 rounds of scanning:
Dead Classes (4)
  • CommandModel - entire file dead
  • StringExtensions - entire file dead
  • ApiErrorMapping - entire file dead
  • AuditEntry - model class dead
Unused Fields (4) + Counters (12)
  • ReadOptions - unused JsonSerializerOptions
  • StatusDeleted / StatusInactive - unused constants
  • _createdSources / _sourceLock - unused fields
  • 12 counters across 4 files - never incremented
Other Issues
  • ComputeSha256() duplicated in 2 files
  • 1 commented-out code block
  • 1 TODO flagged for deletion