CLI project layout recommendations/examples

I am creating a package and I want to offer the package as library for others to use inside their project. Additionally, I want people to be able to install it and run it as a CLI.

What are some good examples on how this should be done?

I would prefer to keep it all inside a single repository.

just create a library crate as usual, add bin target as you needed. you can make the cli binary target optional using feature flags. something like:

// Cargo.toml
[lib]
name = "foo"
path = "src/lib.rs"

[[bin]]
name = "foo-client"
path = "src/bin/client.rs"
required-features = ["client"]

[[bin]]
name = "foo-server"
path = "src/bin/server/main.rs"
required-features = ["server"]

[features]
cli = ["server", "client"]
client = []
server = []

you don't need to add an explicit [[bin]] target if organize the files according to cargo's target auto discovery layout and you don't use feature flags to guard it.

you can take a look at probe-rs for some inspiration:

3 Likes

I've found that a lot of my projects are following this directory structure nowadays:

  • /
    • Cargo.toml
    • README.md
    • crates/
      • foo/
        • Cargo.toml
        • ...
      • foo-cli/
        • Cargo.toml
        • ...
      • xtask/
        • Cargo.toml
        • ...

The foo crate is the library where I'll have the bulk of my app logic, whereas the foo-cli crate is a CLI executable that only contains code for wiring app logic up to a CLI.

The xtask crate is a publish = false binary that tends to do odd jobs like compiling the CLI and packaging it in a pretty release archive that can be attached to the GitHub Release by CI.

5 Likes

Ended up using this layout. Works really nice, thanks!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.