The Deska blog
Finding Unused Exports and Dead Files
Learn how to clean up your codebase by finding unused exports and dead files using static analysis and AI agents on a local-first canvas.
· 10 min read
Managing a growing codebase inevitably leads to the accumulation of technical debt, specifically in the form of unreachable code. Finding unused exports and dead files is a critical maintenance task that improves build times, reduces bundle sizes, and lowers the cognitive load for developers navigating the project. While modern bundlers perform tree shaking to exclude unused code from production builds, the source files often remain cluttered with functions, constants, and entire components that are no longer referenced anywhere in the application.
The Cost of Dead Code in Modern Projects
Dead code is more than just a tidy-up issue. It has tangible impacts on the development lifecycle that go beyond simple disk space.
When a repository contains hundreds of unused exports, grep results become noisy and IDE autocompletions suggest outdated utilities. New team members may spend hours trying to understand a complex module only to realize it is not actually used by any entry point. Furthermore, dead files still contribute to the time taken by linting, type checking, and security scanning in CI/CD pipelines.
Identifying these files manually is prone to error. A file might appear unused because it has no imports, but it could be a configuration file or a dynamic entry point. Conversely, a file might be imported but only export members that are never called.
Static Analysis vs Runtime Analysis
There are two primary ways to detect orphaned code.
Static Analysis
This approach examines the source code without executing it. Tools parse the Abstract Syntax Tree (AST) to map the relationships between imports and exports. This is the most common method for finding unused exports. It is fast and safe, but it can struggle with dynamic imports or code that is referenced via string templates.
Runtime Analysis
This involves monitoring which files are actually loaded during execution, either in a development environment or via production telemetry. While highly accurate for identifying truly dead files, it is difficult to set up and can be misleading if certain code paths are only triggered during specific yearly events or rare edge cases.
For most teams, static analysis is the preferred starting point due to its predictability and ease of integration into the local-first development workflow.
Tools and Techniques for Finding Unused Exports
Several specialized tools exist to help developers automate the detection of dead code.
- Knip: This is currently one of the most powerful tools for the JavaScript ecosystem. It identifies unused dependencies, unused exports, and unused class members.
- Ts-prune: A focused tool for TypeScript projects that outputs a list of unused exports.
- Depcheck: Useful for finding unused packages in your package.json, though less focused on internal file exports.
| Tool | Primary Focus | Best Use Case |
|---|---|---|
| Knip | Exports and Dependencies | Large monorepos and complex TS projects |
| ts-prune | TypeScript Exports | Quick checks in small to medium TS apps |
| ESLint | Unused Variables | Local file scope cleanup during coding |
Leveraging AI Agents for Codebase Cleanup
Traditional static analysis tools are excellent at reporting issues, but they leave the cleanup to the developer. This is where AI coding agents change the workflow. By running agents like Claude Code or Codex CLI within a dedicated environment, you can move from detection to resolution much faster.
In Deska, you can arrange your workspace to handle this task efficiently. You might have a terminal panel running Knip in one corner of the canvas, while an AI agent panel sits next to it. Since Deska is local-first, the agent has direct access to your files without them being uploaded to a third party server.
The workflow typically follows these steps:
- Run a static analysis tool in a terminal panel to generate a list of dead exports.
- Use Ask Deska to open the relevant files in the Monaco editor panels.
- Task an AI agent to verify the tool's findings. This is important because tools sometimes flag files that are required for specific build configurations.
- Instruct the agent to remove the exports and update any internal references.
This side-by-side approach ensures that you remain in control. You can zoom out on the canvas to see the terminal output and the code changes simultaneously. If you need to step away, you can use the mobile app to monitor the progress of a long-running analysis or a batch deletion script through the secure relay.
Handling False Positives
No tool is perfect. Static analysis often flags false positives in the following scenarios:
- Public APIs: If you are building a library, your exports are intended for external consumers and will not be used within your own repo.
- Dynamic Imports: Code loaded via
import(\./${path}\)is often invisible to static tracers. - Framework Entry Points: Files like
tailwind.config.jsorvitest.setup.tsare called by external binaries, not by your source code.
To manage this, most tools allow for a configuration file where you can whitelist specific patterns. When using agents, you can provide these constraints in the system prompt to prevent them from deleting essential configuration files.
Integrating Cleanup into Your Workflow
Codebase hygiene should not be a once a year event. It is more effective when integrated into the regular development cycle.
- CI Integration: Run a check for unused exports as part of your pull request pipeline. Set a threshold or simply report the findings as a comment.
- Monthly Audits: Spend one hour a month using a terminal to run a full project scan.
- Feature Deletion: When a feature is deprecated, don't just remove the entry point. Use the command palette to find and remove all associated exports that are now orphaned.
By maintaining a clean workspace, the entire team benefits from faster greps and a clearer understanding of the architecture. Using a visual environment like Deska allows you to manage these complex refactors by keeping all necessary context visible on a single canvas.
FAQ
How to find unused exports in TypeScript?
The most effective way is using a tool like Knip or ts-prune. These tools analyze your tsconfig.json and map the entire graph of your project to identify exports that have no corresponding import statements in other files.
Is it safe to delete dead files automatically?
It is generally safe for internal application code but risky for libraries or projects using heavy reflection and dynamic imports. Always run your test suite after a bulk deletion and use a version control system to revert any accidental removals.
Can AI agents find dead code?
Yes, AI agents can be very effective at identifying dead code by traversing your file system. They are particularly good at understanding context that static analysis might miss, though they work best when combined with traditional tools to ensure 100% coverage.
Get Started with Deska
If you are ready to clean up your codebase, Deska provides the perfect environment to run analysis tools and AI agents together. You can download the app for Mac, Windows, or Linux and start organizing your refactoring tasks on an infinite canvas.