Crate Kickstart: Essential Tips for Bootstrapping a Rust Project With Modern Tooling
Recently, I was working on the AI_Devs course, which aims to teach how AI agents work and how to create them. I completed all the exercises using the Rust programming language, and during that time, I started developing a common library to group code that could be shared across different subprojects for the course. After finishing the entire course, one file — agent.rs
— stood out to me as particularly useful in most of the exercises. This was the initial implementation of my library, AgentAI.
When I checked crates.io, I was surprised to find that no one had published a library with such functionality. Based on my experience, I decided to release my library to the public so others could benefit from its functionality.
Releasing a library is pretty straightforward: you just provide the details in Cargo.toml and execute cargo publish. There are thousands of such libraries on crates.io. However, simply publishing a library isn’t enough because only the author knows how to use it properly, which doesn’t encourage others to adopt it. In this post, I want to focus on what a good library should have in its repository.
Creating a New Crate and repository #
Every story needs a starting point, and all the projects I’ve mentioned previously get this part right: setting up the project and then publishing it. But your work shouldn’t be limited to that. The number of options in the Cargo.toml
file can be overwhelming, but they are important for your package’s recognition. Which ones are required? Which can be safely skipped? Which are displayed on the crates.io page? In this section, I’ll briefly summarize the essentials of a good Cargo.toml
file.
Everything begins with a simple command:
cargo new --lib <crate_name>
This will generate a very minimalistic Cargo.toml file. For now, I’ll ignore the [dependencies]
section since it is not required for what we want to do. Let’s take a deeper dive into the [package]
section. By default, it contains the fields: name
, version
, and edition
. To complete the file, I suggest adding the following elements:
description
: A short, one-sentence summary of the library’s functionality. This description will be visible next to your crate name in the registry, so it’s important to convey the essence of your library to help others find it. If you’re unsure what to write, you can always ask an LLM for assistance!readme
: The name of the README file. Cargo will try to guess this file, but I suggest providing it explicitly to ensure it is correctly attached to the package. The README file is important because it will be used for the distribution information attached to your crate.license
orlicense-file
: Use only one of these fields. Use the former for well-known licenses (e.g., MIT or Apache-2.0), and the latter if you are using a custom license provided as a file in the repository. Although these fields are optional, I strongly suggest deciding on a license from the beginning. Uncertainty about licensing can discourage some people from using your crate, and there may be legal limitations depending on the country or company policy. In both cases I still suggest attachingLICENSE
file in the repository.authors
: This field consists of a list of strings. You can provide just your name, and it’s conventional to include your email address in “<>”.repository
: The URL of the repository. This information is present in the search and package page. In my opinion, this field is more important thanhomepage
(which you may not yet have). Often, after finding an interesting library, I visit the repository to learn about its current status, available support, usage examples, code quality, etc. I would avoid using the repository URL as thehomepage
to prevent confusion.
These are my essential fields for Cargo.toml
, but your experience may vary.
After setting up the project structure, I suggest creating a repository. The easiest approach is to use GitHub. My further steps will assume this is your choice.
How should you name the repository? I suggest adding the rust
prefix to your package name from Cargo.toml
. For AgentAI, I chose rust-agentai
. Why this way? From time to time, searching GitHub for libraries provides me a better experience. By including rust
in the repository name, the search engine will find it more easily, and you’ll ensure that your target audience is Rust developers. The crates.io search engine doesn’t always provide the best results, so I often use multiple sources when searching for popular libraries. Having rust in the title ensures that I reach the target audience more effectively.
Our preparations pay off during repository creation, as it also requires a short description, which can be copied from the Cargo.toml file. At this point, you should initialize a local repository and push all files to GitHub:
git init
git add .
git commit -m "First commit"
git remote add origin <your_repository_url>
git push -u origin master
No README.md
file for now; we’ll get back to it later.
cargo doc #
It may sound counterintuitive to focus on code documentation before creating a README file, but please stay with me, and I’ll explain why. Each time you publish a new version of your library, crates.io automatically generates documentation from the source code and publishes it on docs.rs. This convenient feature forces you to keep your documentation up to date. This would typically require maintaining two copies of README information: one on the frontend page of the docs and another in the README file. But do we really need to do this? Why not move the common parts of the README to the library documentation and later include it in the README file using the cargo rdme
command? Let’s do that! Open the src/lib.rs
file and add the following at the beginning:
//! # <CRATE NAME>
//!
//! Two sentence information about this crate, what problem it addresses,
//! what technologies it requies (WASM, async?)
//!
What sections are worth including here? Here are a few examples that I often use:
How to install? #
It’s a good idea to inform users how to install your library and whether it requires any external dependencies (e.g., serde_json requires serde). It may sound obvious, but it is always better to make it explicit. This also ensures users are informed about the package name. Continue editing src/lib.rs
from where you left off and add this to the file:
//! ## Instalation
//! To install package enter this command in root for your project:
//!
//! ```bash
//! cargo add <crate_name>
//! ```
//!
Usage #
Another good idea is to show a short snippet of code that highlights the biggest benefit of this library. Continue editing src/lib.rs
from where you left off and add this to the file:
//! ## Usage
//! To install package enter this command in root for your project:
//!
//! ```rust
//! fn main() {
//! println!("{}", crate_name::init());
//! }
//! ```
//!
Examples #
It’s great to include information on where examples are located. Here I use one small trick that I will explain later. Continue editing src/lib.rs
from where you left off and add this to the file:
//!## Examples
//!
//! For more examples, check out the [examples](crate::examples) directory. You can build and run them using Cargo with the following command:
//!
//! ```bash
//! cargo run --example <example_name>
//! ```
//!
Preview #
You can easily preview your documentation by entering this command into terminal:
cargo doc --open
README.md #
Now we can generate README.md file from cargo doc
. I suggest to use cargo-rdme
, which can generate README file for you. First, install it:
cargo install cargo-rdme
Create a README.md
file and paste this content into it:
<!-- cargo-rdme -->
Each time you update cargo doc
, you can regenerate the README file with the following command:
cargo rdme
This README file will be read by crates.io and used as your project description.
Part 2 #
In Part 2, I will cover automation for publishing new releases and how to use GitHub Actions to assist in this process. By using release-plz and a few clever tricks, you can minimize the time required for releasing new versions. I’ll keep you updated when Part 2 is ready and published.