Publishing to crates.io
Publishing a crate to crates.io makes it available to the ecosystem via cargo add. Success requires correct metadata, semver discipline, and a clean cargo package dry run.
Recipe
cargo publish --dry-run
cargo package --list
cargo login # one-time token
cargo publish[package]
license = "MIT OR Apache-2.0"
description = "Short summary"
repository = "https://github.com/you/crate"When to reach for this: Sharing a library beyond your workspace or open-sourcing reusable Rust code.
Working Example
Prepare and publish version 0.2.0:
[package]
name = "valid-types"
version = "0.2.0"
edition = "2024"
rust-version = "1.97"
license = "MIT OR Apache-2.0"
description = "Newtypes for domain identifiers"
repository = "https://github.com/acme/valid-types"
readme = "README.md"
keywords = ["newtype", "validation"]
categories = ["development-tools"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]cargo test --all-features
cargo doc --no-deps
cargo publish --dry-run
cargo publishWhat this demonstrates:
- Required legal and discovery metadata for crates.io
docs.rsmetadata builds docs with all features- Dry run catches packaging mistakes before upload
- Semver bump reflects API changes since
0.1.0
Deep Dive
Pre-Publish Checklist
| Step | Command |
|---|---|
| Tests green | cargo test --all-features |
| Clippy clean | cargo clippy -- -D warnings |
| Docs build | cargo doc --no-deps |
| Tarball sane | cargo package --list |
| License files present | LICENSE-MIT, LICENSE-APACHE |
Versioning Policy
0.y.z- treat minoryas breaking for pre-1.0 crates (ecosystem convention)1.0.0- stable API promise; breaking changes need major bump- Changelog entry for every publish (Keep a Changelog format)
yank vs delete
cargo yank --version 0.1.1- Yank prevents new resolves; existing lockfiles may still use it
- Deletion is not supported; publish a patch release instead
Gotchas
- Missing LICENSE file - publish rejected. Fix: include SPDX files matching
licensefield. - Publishing path dependencies - crates.io rejects
path = "../...". Fix: publish dependencies first or use version deps only. - Breaking change in patch - downstream builds break trust. Fix: follow semver; use
cargo-semver-checksin CI for libraries. - Huge package from
target/or data - useexcludeinCargo.toml. Fix:cargo package --listreview. - Token in shell history - use
cargo logininteractive or CI secretCARGO_REGISTRY_TOKEN.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Private registry | Internal crates only | Open-source ecosystem crates |
| Git dependency | Pre-release consumers | Stable public API |
cargo install from git | CLI tools not libraries | Reusable library code |
FAQs
Can I unpublish?
crates.io policy discourages deletion. Yank bad versions and publish fixes.
How do I publish a workspace member?
Run cargo publish -p crate_name from the workspace root; ensure path deps are published or replaced with version deps.
What is crates.io token scope?
Use scoped tokens for CI (publish-only, limited crates) instead of full account tokens.
How does docs.rs get triggered?
Automatically on publish. Configure [package.metadata.docs.rs] for features and --cfg docsrs for doc attributes.
Should I publish 0.1.0 or 1.0.0?
Start 0.1.0 while API is evolving; move to 1.0.0 when you commit to stable semver.
How do I test the packaged crate?
cargo package then cargo install --path target/package/name-version.crate in a temp project.
What about reserved crate names?
Transfer policy exists for squatting disputes; pick unique names early with cargo search.
Can I publish binaries?
crates.io is for libraries; distribute CLIs via cargo install your-cli after publishing the crate with a [[bin]].
How often should I release?
When meaningful fixes or features land; avoid churn releases without changelog entries.
Does publish run tests?
No. CI must gate cargo publish on green cargo test and clippy.
Related
- Cargo Basics -
cargo new --lib - Cargo.toml Explained - metadata fields
- Dependency Management - post-publish updates
- Cargo Best Practices - release hygiene
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.