CARGO-TREE(1)
π³ CARGO-TREE(1) β the manual, but make it cute
okay bestie, welcome to cargo-tree, a General Commands Manual classic π this is the part where we look at your dependency graph and go "oh. oh wow. that's a lot of little guys."
β¨ NAME β¨
cargo-tree β Display a tree visualization of a dependency graph π¦
πΈ SYNOPSIS πΈ
cargo tree [options]
that's it. that's the whole vibe. cargo tree, optionally with some flags, and suddenly your terminal is a family tree π«Ά
π DESCRIPTION π
So like. This command prints a tree of dependencies straight to your terminal. Iconic behaviour, honestly. Here's what a lil simple project looks like when it depends on the rand package:
myproject v0.1.0 (/myproject)
`-- rand v0.7.3
|-- getrandom v0.1.14
| |-- cfg-if v0.1.10
| `-- libc v0.2.68
|-- libc v0.2.68 (*)
|-- rand_chacha v0.2.2
| |-- ppv-lite86 v0.2.6
| `-- rand_core v0.5.1
| `-- getrandom v0.1.14 (*)
`-- rand_core v0.5.1 (*)
[build-dependencies]
`-- cc v1.0.50
See those little (*) marks? π Those packages have been βde-duplicatedβ. Translation: their dependencies were already shown somewhere else in the graph, so Cargo is NOT about to make you read the same subtree twice. It's giving efficiency. It's giving main character energy.
But bestie, if you WANT the duplicates repeated β if you simply must see every single node with your own two eyes β use the --no-dedupe option. Do it. Live your truth. π
The -e flag is how you pick which dependency kinds get displayed. And the βfeaturesβ kind? It switches the output up entirely so you can see the features enabled by each dependency. Like, watch this β cargo tree -e features:
myproject v0.1.0 (/myproject)
`-- log feature "serde"
`-- log v0.4.8
|-- serde v1.0.106
`-- cfg-if feature "default"
`-- cfg-if v1.0.10
okay so read that tree with me π in this tree, myproject depends on log with the serde feature. And then log depends on cfg-if with βdefaultβ features. Chain reaction. Slay.
And ngl, when you're using -e features, it's genuinely helpful to also use the -i flag to show how the features flow into a package. The examples below go into more detail on that β stay tuned, we're getting there π
π§ Feature Unification π§
Okay this part is important, so lock in π
This command shows you a graph that's much closer to a feature-unified graph β you know, the thing Cargo will actually build β rather than whatever you literally listed in Cargo.toml. For instance: say you specify the same dependency in both [dependencies] and [dev-dependencies], but with different features turned on. This command may merge all the features and slap a (*) on one of the dependencies to indicate the duplicate. Mystery solved, the (*) was never random β¨
So as a result:
- for a mostly equivalent overview of what
cargo builddoes,cargo tree -e normal,buildis pretty close - for a mostly equivalent overview of what
cargo testdoes,cargo treeis pretty close
π¨ BUT. And this is a big but. It doesn't guarantee the exact equivalence to what Cargo is going to build, because a compilation is complex and depends on lots of different factors. Do not come for me, I am simply relaying the facts. π
To learn more about feature unification, check out this dedicated section: https://doc.rust-lang.org/cargo/reference/features.html#feature-unification π
more coming, bestie, don't go anywhere π
β¨ OPTIONS β¨
okay bestie buckle UP because this is the part where we get into the flags and there are a LOT of them and every single one of them matters π
π³ Tree Options
-i spec,--invert specβ shows you the reverse dependencies of the package you name. Like, instead of "what does this thing need", it flips the whole tree around and shows you "who needs this thing". Inverted tree, main character energy π¦
heads up though: inside a workspace, by default it'll only show you the package's reverse deps that live inside the tree of the workspace member sitting in your current directory. Want the whole workspace? hit it with--workspaceand it'll extend out to cover the entire workspace. And if you use-p, it'll show the reverse deps only within the subtree of the package you handed to-p. iykyk π
--prune specβ yeets the named package right out of the dependency tree display. gone. not invited to the party π--depth depthβ sets the max display depth of the dep tree.--depth 1= just the direct dependencies, for example. keep it shallow bestie β¨--no-dedupeβ turns OFF de-duplication of repeated dependencies. so normally when a package has already shown its deps, any further times it shows up it won't re-display them and instead slaps a(*)on there to say "yeah we've been here already". this flag makes all those dupes get repeated instead. no cap π-d,--duplicatesβ only shows dependencies that come in multiple versions (and yeah, it implies--invert). when you pair it with-p, it only shows duplicates inside the subtree of the package you gave it. lowkey a lifesaver for build times and executable sizes β building the same package multiple times is giving wasteful π so this flag helps you find the offending packages, and then you can go investigate whether the package depending on the older duplicate version can be updated to the newer one so only one instance ever gets built. slay πΈ-e kinds,--edges kindsβ which dependency kinds to display. takes a comma-separated list, and here's your menu:allβ show all edge kinds.normalβ show normal dependencies.buildβ show build dependencies.devβ show development dependencies.featuresβ show features enabled by each dependency. and listen, if this is the only kind you give, it automatically includes the other dependency kinds too πͺno-normalβ do not include normal dependencies.no-buildβ do not include build dependencies.no-devβ do not include development dependencies.no-proc-macroβ do not include procedural macro dependencies.
β οΈ real talk: thenormal,build,dev, andalldependency kinds cannot be mixed withno-normal,no-build, orno-devdependency kinds. pick a lane bestie.
default is normal,build,dev π
--target tripleβ filters dependencies to match the given target triple (<https://doc.rust-lang.org/cargo/appendix/glossary.html#target>). default is the host platform. and if you want everything, passallto include all targets π
π Tree Formatting Options
--charset charsetβ picks the character set for drawing the tree. valid values are"utf8"or"ascii". default is"utf8"β¨ (the pretty one, obviously)-f format,--format formatβ sets the format string for each package. default is"{p}". it's an arbitrary string used to display each package, and these bits get swapped for the real values:{p}β the package name.{l}β the package license.{r}β the package repository URL.{f}β comma-separated list of package features that are enabled.{lib}β the name, as used in ausestatement, of the package's library.
obsessed with how customizable this is fr fr π«Ά
--prefix prefixβ controls how each line gets displayed.prefixcan be one of:indent(default) β shows each line indented as a tree.depthβ shows it as a list, with the numeric depth printed before each entry.noneβ shows it as a flat list.
three whole vibes, pick your fave π
π¦ Package Selection
By default, when you don't give any package selection options, which packages get selected depends on the selected manifest file (based on the current working directory, unless --manifest-path is given). If the manifest is the root of a workspace, then the workspace's default members get selected β otherwise only the package defined by that manifest is selected. periodt.
The default members of a workspace can be set explicitly with the workspace.default-members key in the root manifest. And if that's not set? A virtual workspace includes all workspace members (equivalent to passing --workspace), and a non-virtual workspace includes only the root crate itself. the way it just decides for you π
-p specβ¦,--package specβ¦β display only the specified packages. checkcargo-pkgid(1)for the SPEC format. you can pass this flag multiple times, and it supports common Unix glob patterns like*,?and[]. BUT β and this is the important bit β to stop your shell from accidentally expanding those glob patterns before Cargo ever gets to handle them, you must wrap each pattern in single quotes or double quotes. do not skip this step bestie π--workspaceβ display all members in the workspace. all of them. every single one π--exclude SPECβ¦β exclude the specified packages. it must be used together with the--workspaceflag. can be specified multiple times, and supports common Unix glob patterns like*,?and[]. and same warning as before: wrap each pattern in single quotes or double quotes so your shell doesn't expand it before Cargo can handle it. no cap π
π Manifest Options
--manifest-path pathβ path to theCargo.tomlfile. by default, Cargo searches forCargo.tomlin the current directory or any parent directory. it'll go looking for you π¦--frozen,--lockedβ either one of these flags requires that theCargo.lockfile is up-to-date. if the lock file is missing, or it needs to be updated, Cargo will exit with an error. the--frozenflag also stops Cargo from trying to access the network to figure out if it's out-of-date.
these are your go-tos for environments where you want to assert that Cargo.lock is up-to-date (like a CI build) or where you want to avoid network access entirely π
--offlineβ prevents Cargo from accessing the network for literally any reason. without this flag, Cargo stops with an error if it needs the network and the network isn't there. with this flag, Cargo will try to proceed without the network if it can.
β οΈ beware bestie: this may result in different dependency resolution than online mode. Cargo restricts itself to crates that are already downloaded locally, even if there might be a newer version as indicated in the local copy of the index. see the cargo-fetch(1) command to download dependencies before you go offline.
may also be specified with the net.offline config value (<https://doc.rust-lang.org/cargo/reference/config.html>). πΈ
π Feature Selection
The feature flags let you control which features are enabled. when you give no feature options at all, the default feature is activated for every selected package. it's giving autopilot β¨
See the features documentation (<https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>) for more details.
-F features,--features featuresβ a space- or comma-separated list of features to activate. features of workspace members can be enabled withpackage-name/feature-namesyntax. and you can pass this flag multiple times β which enables all the specified features π«Ά--all-featuresβ activate all available features of all selected packages. go big or go home π--no-default-featuresβ do not activate the default feature of the selected packages. sometimes you just don't want the default, and that's valid π
π₯οΈ Display Options
-v,--verboseβ use verbose output. you can specify it twice for "very verbose" output, which includes extra output like dependency warnings and build script output. may also be specified with theterm.verboseconfig value (<https://doc.rust-lang.org/cargo/reference/config.html>). spill the tea β-q,--quietβ do not print cargo log messages. may also be specified with theterm.quietconfig value (<https://doc.rust-lang.org/cargo/reference/config.html>). silence is golden π--color whenβ controls when colored output is used. valid values:auto(default): automatically detect if color support is available on the terminal.always: always display colors.never: never display colors.
may also be specified with the term.color config value (<https://doc.rust-lang.org/cargo/reference/config.html>). the aesthetic matters π
π« Common Options
+toolchainβ if Cargo was installed with rustup, and the first argument tocargobegins with+, it gets interpreted as a rustup toolchain name (like+stableor+nightly). see the rustup documentation (<https://rust-lang.github.io/rustup/overrides.html>) for more info on how toolchain overrides work β¨--config KEY=VALUEorPATHβ overrides a Cargo configuration value. the argument should be in TOML syntax asKEY=VALUE, or given as a path to an extra configuration file. may be specified multiple times. see the command-line overrides section (<https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>) for more info π¦-C PATHβ changes the current working directory before running any specified operations. this affects stuff like where cargo looks by default for the project manifest (Cargo.toml), and the directories searched for discovering.cargo/config.toml, for example. this option must appear before the command name, likecargo -C path/to/my-project build.
β οΈ this option is only available on the nightly channel (<https://doc.rust-lang.org/book/appendix-07-nightly-rust.html>) and requires the -Z unstable-options flag to enable (see #10098 <https://github.com/rust-lang/cargo/issues/10098>). nightly girlies only π
-h,--helpβ prints help information. your bestie when you forget everything π-Z flagβ unstable (nightly-only) flags to Cargo. runcargo -Z helpfor details. the forbidden knowledge π
π ENVIRONMENT
See the reference (<https://doc.rust-lang.org/cargo/reference/environment-variables.html>) for details on environment variables that Cargo reads. it's reading your env, bestie, it knows everything π
π¦ EXIT STATUS
0: Cargo succeeded. slay π101: Cargo failed to complete. we've all been there π
EXAMPLES π
okay bestie, vibe check: these are the canonical ways to flex cargo tree. commands are sacred β copy them exactly, no cap. β¨
- Display the tree for the package in the current directory:
cargo tree
- Display all the packages that depend on the
synpackage:
cargo tree -i syn
- Show the features enabled on each package:
cargo tree --format "{p} {f}"
- Show all packages that are built multiple times. This can happen if multiple semver-incompatible versions appear in the tree (like
1.0.0and2.0.0).
cargo tree -d
- Explain why features are enabled for the
synpackage:
cargo tree -e features -i syn
The -e features flag is used to show features. The -i flag is used to invert the graph so that it displays the packages that depend on syn. An example of what this would display:
syn v1.0.17
|-- syn feature "clone-impls"
| `-- syn feature "default"
| `-- rustversion v1.0.2
| `-- rustversion feature "default"
| `-- myproject v0.1.0 (/myproject)
| `-- myproject feature "default" (command-line)
|-- syn feature "default" (*)
|-- syn feature "derive"
| `-- syn feature "default" (*)
|-- syn feature "full"
| `-- rustversion v1.0.2 (*)
|-- syn feature "parsing"
| `-- syn feature "default" (*)
|-- syn feature "printing"
| `-- syn feature "default" (*)
|-- syn feature "proc-macro"
| `-- syn feature "default" (*)
`-- syn feature "quote"
|-- syn feature "printing" (*)
`-- syn feature "proc-macro" (*)
To read this graph, you can follow the chain for each feature from the root to see why it is included. For example, the βfullβ feature is added by the rustversion crate which is included from myproject (with the default features), and myproject is the package selected on the command-line. All of the other syn features are added by the βdefaultβ feature (βquoteβ is added by βprintingβ and βproc-macroβ, both of which are default features).
If youβre having difficulty cross-referencing the de-duplicated (*) entries, try with the --no-dedupe flag to get the full output.
SEE ALSO π
go read those too, theyβre the besties of this page. π«Ά
later, bestie π
β thatβs a wrap on CARGO-TREE(1), and the source/version and date are chilling in the footer like the main characters they are. Iβm not copy-pasting that line, but you know exactly where to find it. mwah πβ¨
π¦ where this page comes from
- ubuntu jammy: cargo-1.76 1.76.0+dfsg0ubuntu1~bpo0-0ubuntu0.22.04.1 Β· Apache-2.0 WITH LLVM exception
- ubuntu noble: cargo-1.76 1.76.0+dfsg0ubuntu1-0ubuntu0.24.04.2 Β· MIT OR Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms