# Find Dead Code in a Vue Project

Yes. An agent runs knip over your Vue app, checks each unused file, export and dependency against the type check, build and tests, and reports what is safe to drop.

[Run this on Rush](https://cloud.getrush.ai/run/find-dead-code/vue/), in a Project that has your repository.

## What the agent does

The agent reads the build and test setup before it runs any tool, because dead-code finders are only as good as their list of entry points. In a Vue app like `mutoe/vue3-realworld-example-app`, `index.html` loads `src/main.ts`, which creates the app with Pinia and the router and registers global components from `src/plugins`. `vite.config.ts` aliases `src/*` and configures Vitest with `happy-dom`, a setup file at `src/setup-tests.ts` and coverage through a custom provider; `tsconfig.json` is strict with `noUnusedLocals` and `noUnusedParameters` and references a second config under `playwright/`. `package.json` runs on `pnpm@10.33.0` with `type-check` through `vue-tsc`, `lint` through ESLint 10, `test:unit` through Vitest, `test:e2e` through Playwright, and a `generate:api` script that regenerates `src/services/api.ts` from the RealWorld OpenAPI file with `swagger-typescript-api`. `.github/workflows/test.yml` runs type-check, lint, build, the unit tests and the e2e suite.

That reading becomes the knip configuration. Entry points are `src/main.ts`, the Playwright specs and fixtures under `playwright/`, `scripts/merge-coverage.ts`, `vite.config.ts` and the three files under `config/`. `src/services/api.ts` is generated, so its unused exports are expected and the report lists them under their own heading rather than as findings; the `size-limit` and `simple-git-hooks` entries in `package.json` are tools the config references, not code. With that in place, `knip` reports unused files, unused exports and types, and dependencies nothing imports.

Then each candidate is checked, because knip reports what it cannot see, not what is dead. For an unused file, the agent removes it and runs `pnpm type-check` and `pnpm build`; for an unused export, it removes the `export` keyword and runs the same two plus `pnpm test:unit`, since the spec files next to each component under `src/components` and `src/pages` import from them; for an unused dependency, it removes the package and runs the build and the unit tests. A candidate that breaks any of the three is listed as a false positive with the command that failed.

The result is `dead-code.md`: one table per kind with the path, the line, what referenced it last according to `git log`, and which checks it passed, and a closing section on what knip could not see, such as components registered globally by name in `src/plugins`. The repository is left as it was; the removals are tried on a branch inside the sandbox and reverted.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Find dead code in this Vue app and change nothing in the repository. Read index.html, src/main.ts, src/plugins, vite.config.ts, tsconfig.json, package.json, playwright/tsconfig.json and .github/workflows/test.yml first, and configure knip with every entry point they name, treating src/services/api.ts as generated. Run knip, then check each unused file, export and dependency by removing it on a scratch branch and running pnpm type-check, pnpm build and pnpm test:unit. Write dead-code.md with one table per kind giving the path, the line, the last commit that touched it and the checks that passed, a list of false positives with the command that failed, and a section on what the tool cannot see. Leave the working tree clean.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is `dead-code.md` as an artifact on the session, with a `url` on `api.prix.dev` that downloads it without a key until `url_expires_at`, and the same file through the artifacts route with the key. The session's `result` summarizes the counts per kind. The repository has no new commit and no branch; the transcript ends with a clean `git status`.

Each row names a path, a line, the commit that last touched it and the three checks it survived, so a reviewer can open the file, confirm nothing imports it, and decide. The generated API client's unused methods are listed apart, as expected, and the false positives explain which check failed, which is often the most useful part for the next person who runs knip.

The transcript holds the knip run with its full output and each check with its output, so a row can be traced to the command that justified it. A follow-up message to the same session can ask for the safe removals to be applied and opened as a pull request, and the sandbox already has the app installed.

## Run it on every first Monday of the month

In the console, add an automation to the Project with a `schedule` trigger set to a `cron` expression for the first Monday and your `timezone`, and this prompt. Each run writes a fresh report as its artifact, so the month's new dead code shows up as new rows against the last report.

From your own server, the same request with a `webhook_url` on the API key posts `run.completed` when the turn finishes; the handler downloads `dead-code.md` from the session and files it where the team reads it. An `Idempotency-Key` built from the month makes a retried request return the same run.

## Why run it on Rush?

Running knip is a minute; checking its output is the work, because every candidate needs a type check, a build and a test run after its removal, and a Vite build plus a Vitest run over an app many times over is an afternoon on a laptop. The sandbox installs with pnpm once and runs the loop as many times as there are candidates, and nothing it removes touches your checkout.

The report is only worth reading if each row carries its evidence, and the transcript keeps the commands behind every row. Several front ends can be scanned at once, each in its own sandbox, each producing its own file, up to the key's `max_concurrent` limit.

## Frequently asked questions

### Will it delete anything from my repository?

No. The removals happen on a scratch branch inside the sandbox to run the checks, and the branch is discarded; the result is the report. Ask in a follow-up for the safe rows to be applied and the agent opens a pull request from the same sandbox.

### Why does the generated API client get its own section?

Because `src/services/api.ts` is written by `swagger-typescript-api` from the OpenAPI file and regenerated by the `generate:api` script, so removing a method from it would come back on the next run. The report lists those unused methods for information and keeps them out of the removal candidates.

### Why not just run knip in CI?

Do that too, with the configuration the agent writes, so new dead code is caught at review. The one-off report is for the backlog that exists today, where each row needs the build and test checks before someone removes it, and that is what the run does.

### Does it catch unused component props or unused code inside a function?

No. knip works at the file, export and dependency level, and `vue-tsc` already enforces `noUnusedLocals` in this project, which covers locals and parameters. Unused props and branches that can never run are a different kind of analysis, and the report's last section says so.
