Analyze dead code in TypeScript/JavaScript projects using Claude Code and Knip.
- Static analysis - Uses Knip for comprehensive dead code detection
- AI-powered insights - Claude analyzes results and provides actionable recommendations
- PR mode - Focuses on changed files and posts comments on pull requests
- Comprehensive mode - Full codebase analysis with GitHub issue creation
- Rich reporting - Markdown reports, JSON artifacts, and GitHub integration
This action requires:
- Knip - Dead code detection tool
- Install:
npm install -D knip(orpnpm add -D knip) - Optional: Create
knip.jsonfor configuration
- Install:
pnpm add -D knipOptionally create knip.json:
{
"$schema": "https://unpkg.com/knip@latest/schema.json",
"entry": ["src/index.ts"],
"project": ["src/**/*.ts"]
}Create .github/workflows/dead-code.yml:
name: Dead Code Analysis
on:
pull_request:
types: [opened, synchronize]
paths:
- "**/*.ts"
- "**/*.tsx"
- "!**/*.test.ts"
- "!**/*.spec.ts"
schedule:
# Weekly comprehensive analysis - Monday 9:00 AM UTC
- cron: "0 9 * * 1"
workflow_dispatch:
permissions:
contents: read
pull-requests: write
issues: write
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- name: Analyze Dead Code
uses: ModernRelay/ralph-claude-code-actions/dead-code-analyzer@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ secrets.GITHUB_TOKEN }}Add CLAUDE_CODE_OAUTH_TOKEN to your repository secrets:
- Run
claude /loginlocally - Copy the OAuth token
- Add to GitHub repository secrets
When triggered by a pull request, the action:
- Detects changed TypeScript/JavaScript files
- Runs Knip for static analysis
- Analyzes changes for new dead code
- Posts a comment on the PR with findings
- uses: ModernRelay/ralph-claude-code-actions/dead-code-analyzer@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ secrets.GITHUB_TOKEN }}
pr_number: ${{ github.event.pull_request.number }}For scheduled or manual runs, the action:
- Analyzes the entire codebase
- Categorizes issues by priority
- Creates a GitHub issue with findings
- uses: ModernRelay/ralph-claude-code-actions/dead-code-analyzer@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ secrets.GITHUB_TOKEN }}
create_issue: "true"
issue_labels: "dead-code,tech-debt,automated"| Input | Required | Default | Description |
|---|---|---|---|
claude_code_oauth_token |
Yes | - | Claude Code OAuth token |
github_token |
No | - | GitHub token for PR comments/issues |
pr_number |
No | Auto-detected | Pull request number |
changed_files |
No | Auto-detected | Changed files (newline-separated) |
config_path |
No | knip.json |
Path to Knip config |
working_directory |
No | . |
Working directory |
package_manager |
No | pnpm |
Package manager (npm/yarn/pnpm) |
install_command |
No | Auto | Custom install command |
knip_args |
No | - | Additional Knip arguments |
model |
No | sonnet |
Claude model to use |
max_turns |
No | 100 |
Max Claude turns |
create_issue |
No | true |
Create issue in comprehensive mode |
issue_labels |
No | dead-code,automated |
Labels for issues |
| Output | Description |
|---|---|
result |
clean or issues-found |
issues_count |
Number of issues found |
report_path |
Path to the report file |
- Unused files - Files not imported anywhere
- Unused dependencies - Packages in package.json not used
- Unresolved imports - Imports pointing to non-existent files
- Backward-compat shims -
_unusedvariables, unnecessary re-exports
- Unused exports - Exported but never imported elsewhere
- Commented-out code - Large blocks of commented code
- Duplicate exports - Same thing exported multiple ways
- Unused types - Type definitions never referenced
- Dead patterns - Always-true conditions, unreachable code
## 🧹 Dead Code Analysis
| Status | Issues |
|--------|--------|
| ⚠️ | 3 |
### Issues Found
- **src/utils/helpers.ts:42** - Unused export `formatDate`
- **src/components/Button.tsx:15** - Unused import `useCallback`
- **src/lib/api.ts:78** - Unused function `legacyFetch`
<details>
<summary>Knip Output</summary>
Unused exports:
- src/utils/helpers.ts: formatDate
...
</details>For best results, configure Knip for your project. Example knip.json:
{
"$schema": "https://unpkg.com/knip@latest/schema.json",
"entry": ["src/index.ts", "src/main.tsx"],
"project": ["src/**/*.{ts,tsx}"],
"ignore": ["**/*.test.ts", "**/*.spec.ts"],
"ignoreDependencies": ["@types/*"],
"ignoreWorkspaces": ["packages/legacy"]
}See Knip documentation for all options.
For monorepos, Knip automatically detects workspaces. Configure each workspace:
{
"workspaces": {
"packages/*": {
"entry": ["src/index.ts"]
},
"apps/web": {
"entry": ["src/main.tsx", "src/pages/**/*.tsx"]
}
}
}MIT