# cargo-machete: Finding Unused Rust Dependencies

> cargo-machete scans Rust projects for dependencies that appear unused, with optional Cargo metadata analysis for renamed crates, feature-specific builds, and generated code. It is useful for cleanup and CI checks, but its documented fast analysis can produce false positives.

**bnjbvr/cargo-machete** — Remove unused Rust dependencies with this one weird trick!

- Repository: https://github.com/bnjbvr/cargo-machete
- Stars: 1,398 · Forks: 56
- Language: Rust
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/bnjbvr-cargo-machete

## Why cargo-machete Targets Cargo Dependency Cleanup

cargo-machete addresses a specific Rust maintenance problem: packages listed in `Cargo.toml` that no longer have a visible use in the project source. Its intended audience is Rust developers working with Cargo who want to identify dependency declarations that may remain after code is removed or moved. The project describes itself as both fast and imprecise, which is an important boundary. It is better understood as a detector for possible unused dependencies than as a fully authoritative dependency compiler.

The tool can examine a directory containing one or more Rust projects. That makes it relevant to both a single crate and a workspace, although the README does not define a workspace-wide reporting format beyond showing configuration in a workspace `Cargo.toml`. It also exposes process exit codes, JSON output, Docker packaging, a GitHub Action, and a `pre-commit` hook. Those integration points make it usable outside an editor, particularly when a project wants dependency declarations reviewed automatically.

Cargo-machete does not replace Cargo's dependency resolver. It checks whether declared packages seem to be used after the manifest has defined the dependency set. That distinction matters when judging the output: removing a suggested package can change compilation, feature resolution, build scripts, generated code, or platform-specific behavior. The README documents analysis and reporting, but it does not promise automatic manifest rewriting or a command for deleting dependencies.

## How cargo-machete Scans Manifests and Source

The documented behavior points to a source-oriented scan. A dependency can be reported even when its crate name is not visible in the files that cargo-machete checks. The renamed-crate example is especially revealing: without `--with-metadata`, a dependency such as `rustls-webpki` can differ from the import name used by source, producing a false positive. The explicit `[package.metadata.cargo-machete.renamed]` mapping tells cargo-machete that `rustls-webpki` should be checked as `webpki`.

The repository manifest also lists dependencies such as `grep`, `ignore`, `rayon`, and `walkdir`. Based on that layout, the implementation is equipped to search files while walking project directories and process work through multiple threads. The README does not expose the internal analysis algorithm, its file exclusions, or its handling of every Cargo target, so those details should not be inferred from the dependency list alone.

Cargo metadata supplies a different analysis path through `--with-metadata`. According to the README, this flag calls `cargo metadata --all-features` to determine final dependency names and produce more accurate information per build type. This is a concrete alternative to the default source-oriented approach when a scan produces too many false positives. It is not free of side effects: the README warns that it may modify project `Cargo.lock` files. For generated dependencies such as `prost`, the documented resolution is instead to declare an ignored dependency in package or workspace metadata.

## Installing cargo-machete and Running a First Scan

The README gives a direct Cargo installation command. This installs the command in the local Cargo environment so it can be invoked as a Cargo subcommand.

```bash
cargo install cargo-machete
```

Move into a directory containing a Rust project, or pass an absolute directory path to the subcommand. The two documented forms are:

```bash
cd my-directory && cargo machete
cargo machete /absolute/path/to/my/directory
```

The exit code is the simplest result for a terminal user or CI job. A return code of `0` means no unused dependencies were found, `1` means at least one was found, and `2` means processing failed. A code of `2` does not provide an indication about unused dependencies, so a script should not treat processing failure as a clean dependency check.

For automation that needs structured details, add `--json`. The README shows `{}` when no unused dependencies are found and a `crates` array when unused entries exist. The output also includes fields such as `package_name`, `manifest_path`, `unused`, and `ignored_used`. This format is more suitable for another program than parsing the human-readable report.

## Handling Generated Code and Renamed Crate Names

The main operational risk is accepting a report without reviewing the reasons behind it. The documented example involves `prost`, which is described as being used by output generated from `build.rs`. A normal source scan cannot confirm that generated code, so the dependency is marked ignored for the affected package or workspace.

```toml
[package.metadata.cargo-machete]
ignored = ["prost"]
```

For a workspace manifest, the README gives the corresponding workspace-level configuration:

```toml
[workspace.metadata.cargo-machete]
ignored = ["prost"]
```

Ignored is a suppression mechanism, not evidence that the dependency is unnecessary. The report distinguishes ignored entries that were detected as unused, so the configuration remains visible to whoever reviews the scan. This is preferable to silently removing a package that a build process relies on.

A renamed dependency needs a different correction. The `ignored` setting suppresses a known false positive, while the `renamed` table maps the package name to the identifier that appears in source:

```toml
[package.metadata.cargo-machete.renamed]
rustls-webpki = "webpki"
```

This mapping allows cargo-machete to detect when the dependency is genuinely unused. If many dependencies are renamed or feature resolution obscures their final names, `--with-metadata` may provide a more accurate basis, subject to the documented `Cargo.lock` modification warning.

## CI, Docker, pre-commit, and Exit-Code Semantics

cargo-machete is designed to fit several automation paths, but each path has a different maintenance implication. The documented GitHub workflow checks out the repository and runs the project Action on pull requests. The Action reference in the README is `bnjbvr/cargo-machete@main`, so a workflow that uses that reference follows the branch rather than a pinned release tag.

```yaml
name: Cargo Machete
on:
  pull_request: { branches: "*" }

jobs:
  detect-unused-dependencies:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Machete
        uses: bnjbvr/cargo-machete@main
```

For local commit checks, the README supplies a `pre-commit` repository entry with a `cargo-machete` hook. The hook can be pinned to a tag or commit instead of `main`. That choice affects reproducibility: an unpinned branch can change as the Action or hook definition changes.

Docker is also documented. The image mounts the current directory at `/src` and runs cargo-machete against the container entrypoint. The command is short, but it still depends on the container image and on the Rust project being available through the mount.

```bash
docker run --rm -v $(pwd):/src ghcr.io/bnjbvr/cargo-machete:latest
```

Because the return code distinguishes findings from processing errors, CI should preserve the documented meaning of `0`, `1`, and `2`. A project may want `1` to fail a job, but it should ensure that `2` is not confused with a successful scan.

## Maintenance, Release, and License Boundaries

The repository is not archived. Its last push was on 2026-09-07, and the recent release history includes `v0.9.2` on 2026-04-15. The project therefore has recent release and repository activity, but the README does not describe a long-term support policy or compatibility guarantee for older Rust toolchains. The package uses Rust edition `2024`, and its manifest lists `rustc` compatibility through the README badge as stable, but the exact minimum compiler version is not documented in the README.

Upgrading means installing a newer crate release with Cargo if that is the installation method in use, and checking whether project manifests or lockfiles change. The `--with-metadata` option has a specific operational cost because the README warns that it may modify `Cargo.lock` files. CI and `pre-commit` configurations using `main` also require separate review if the project wants repeatable automation. The README offers a specific tag or commit as the alternative for the hook, and the Action example itself uses `main`.

The project is distributed under the MIT license, with the license file named `LICENSE.md`. That identifier describes the repository's stated licensing choice. This review does not interpret what the license means for a particular downstream use; it only records the declared terms and the files involved. The README does not document a separate support contract or commercial support option.

## Conclusion

cargo-machete is a practical choice for Rust developers who want a fast source scan or a CI check for likely unused dependencies. It detects likely unused dependencies but does not automatically remove them. Before adopting its removal suggestions, verify each dependency against generated sources, feature-specific code, and the result of `cargo machete --with-metadata` if that mode is acceptable.

## FAQ

### How do I install and run cargo-machete for a Rust project?

Install it with `cargo install cargo-machete`, then run `cargo machete` in a directory containing Rust projects or pass an absolute directory path. Exit code `0` means no unused dependencies were found, `1` means at least one was found, and `2` means processing failed.

### How does cargo-machete handle false positives from generated code?

The README documents an `ignored` array under `package.metadata.cargo-machete` or `workspace.metadata.cargo-machete`. It gives `prost` as an example of a dependency used by code generated from `build.rs`.

### When should I use --with-metadata with cargo-machete?

The README suggests `--with-metadata` when there are too many false positives. It calls `cargo metadata --all-features` for final dependency names and more accurate dependency information per build type, but warns that this may modify `Cargo.lock` files.

### Can cargo-machete detect renamed Rust crates?

It can avoid the associated false positive when the import name is recorded in `[package.metadata.cargo-machete.renamed]`. The documented mapping is `rustls-webpki = "webpki"`.

## Sources

- [bnjbvr/cargo-machete on GitHub](https://github.com/bnjbvr/cargo-machete)
- [Issues](https://github.com/bnjbvr/cargo-machete/issues)
- [License: MIT](https://github.com/bnjbvr/cargo-machete/blob/main/LICENSE)
- [README](https://github.com/bnjbvr/cargo-machete/blob/main/README.md)
- [Releases](https://github.com/bnjbvr/cargo-machete/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bnjbvr-cargo-machete
