A crate is Rust's unit of compilation; a package is what Cargo manages. Getting the vocabulary straight makes the whole dependency system click.
Crate vs package
A crate is a single compilation unit — either a binary (has a main) or a library (code other crates use). A package is one Cargo.toml and the crates it builds: a package can hold multiple binary crates and at most one library crate. When you cargo new, you get a package with one crate.
Dependencies from crates.io
You add a dependency by naming it under [dependencies] in Cargo.toml: serde = "1". Cargo fetches it from crates.io (the public registry), resolves compatible versions, and makes it available to use. cargo add serde does the edit for you. The whole ecosystem — over 150,000 crates — is one line away.
Cargo.toml states which versions you accept (serde = "1" means 'any 1.x'). Cargo.lock records the exact versions actually used, so builds are reproducible. Commit Cargo.lock for binaries — it's what makes 'works on my machine' actually transferable.Semantic versioning
Crate versions follow semver: MAJOR.MINOR.PATCH. serde = "1" accepts any 1.x (backward-compatible) but not 2.0 (which may break). This is why editions and semver matter together — the ecosystem can evolve without silently breaking your build, because version bounds encode compatibility promises.