External Publication
Visit Post

Alternative to `cargo new` templates: examples as build-target templates

Rust Internals [Unofficial] March 2, 2026
Source

Looking for thoughts on an alternative idea to what we normally think of as templates for cargo new and some brainstorming on the CLI.

From both the Cargo team and the community, there has long been an interest to having cargo generate-like templates in cargo new (Feature request: Cargo templates · Issue #5151 · rust-lang/cargo · GitHub). However, this is not trivial and has needed someone to work through problems like:

  • Working out the template language to pull into our compatibility guarantees
  • Deciding on the API surface between cargo new and the template, either being exhaustive or having a plan for evolving it
  • Should we and how do we preserve the "smart" features like auto-inheriting
  • How to handle updating from "living" templates. All of my repos have a common git merge base that is the template and this makes it easy to propagate changes out, like with lints. I couldn't live without it
  • How to handle composition. There are project templates, and package templates and how to allow intermixing of them

On that last point, in other discussions I've realized that there is another layer of templates: API templates. These are not whole-package templates but build-target or even mod-specific templates. You might have a CLI template that gets you started with CLI parser, a logger, etc.You might then have a CLI test template that does end-to-end testing of your CLI, capturing SVG snapshots of the output to preserve the colors. You then might find you need to do file watching so you want to pull in a notify template as a mod.

My idea has two parts:

  • cargo new becomes additive, allowing cargo new --lib when there is already a package present, adding a lib
  • We allow specifying a package's examples as your src/lib.rs or src/main.rs. Even better if it could also be build.rs and tests/foo.rs. Amazing if we could also do src/foo/mod.rs.

This way you can pull in examples as you need the behavior and then start editing from there to get what you want.

If we limit this to examples you already have as dependencies, then we could look at the examples required-features and automatically add the features and dependencies that that activates. An example can also rely on dev-dependencies but we don't have a good story for detecting which are relevant and likely would have to just let those example-templates be broken.

Limiting to existing dependencies makes this a bit easier to operate on. However, if we could find a way to make this also work with any package, then this would be amazing for Cargo Script. A big priority for Cargo Script is that it should be light weight enough not to need cargo new support. I've intentionally avoided it to help draw attention to the pain points involved in hand writing them so we can address them.

However, if cargo new could give you more than

#!/usr/bin/env cargo
---
package.edition = "2024"
---

fn main() {
}

and instead could give you

#!/usr/bin/env cargo
---
package.edition = "2024"

[dependencies]
clap = { version = "4.5.30", features = ["derive"] }
---

use clap::Parser;

#[derive(Parser)]
struct Cli {
}

fn main() {
    let cli = Cli::parse();
}

That would be much more powerful.

However, where I'm stuck on this idea is how to design the CLI, keeping in mind

  • build-targets are additive
  • we'd support more kinds of build targets
  • ideally, also support mods
  • select a dependency
  • select the example within the dependency, helping the user choose
  • maybe even allow this for non-dependencies
  • align with Cargo's CLI principles
  • fit within cargo new

Discussion in the ATmosphere

Loading comments...