Create Rust CLI apps with ease.
rust-starter is an empty Rust CLI application with libraries, and few defaults. The goal is to help you bootstrap your next CLI project as quickly as possible while ensuring you make use of the best tools and best-practices that are available today..
There is no configuration required (though we recommend you check all the possible configurations possible). An empty clone will compile, and has a few sample commands. You can start coding right away!
rust-starteris biased toward popular and stable depedencies. These could be changed later, but we make these choices so that you can focus on your CLI functionalities.
rust-startertemplate already compiles and runs, so you don't need to configure anything to get your program working.
rust-starterfollows the idiomatic Rust philosophy. It attempts to follow and stick to the industry best practices.
rust-starter aims to keep things simple.
To get started, simply clone the repository, and run the project.
git clone https://github.com/rust-starter/rust-starter cd rust-starter cargo run
There are no configurations required and no initial code to write. You should get
the following output upon running
rust-starter 1.0.0 Abid Omar
CLI interface USAGE: rust-starter [OPTIONS] [SUBCOMMAND] FLAGS: -h, --help Prints help information -V, --version Prints version information OPTIONS: -c, --config Set a custom config file SUBCOMMANDS: config Show Configuration error Simulate an error hazard Generate a hazardous occurance help Prints this message or the help of the given subcommand(s)
That's it. If you got this output,
successfully compiled and run. You can also run the available subcommands
cargo run config to show the loaded configuration,
cargo run hazard which is a sample subcommand, and
cargo run error to intentionally trigger an error.
rust-starterdo not serve the same purpose.
clapis a library to parse command-line arguments.
rust-starteris a template program that uses
rust-starter makes use of Cargo Workspaces to manage and structure your program. It is possible to have all of the code in a single workspace and the
rust-starter template doesn't need more than one. However, starting this way will help you split code into a separate workspace when you see fit.
The main program is inside
src. Its main purpose is to start the program, the configuration, logging, and then run the arguments parser. It's not supposed to have any functionality. It is recommended that these are added through Workspaces.
rust-starter comes with 3 workspaces.
These different workspaces are libraries. It's preferrable that new workspaces can compile on their own. This makes your code modular and unit testing much simpler. You can add more workspaces if you need to.
rust-starter uses clap to parse Command Line arguments.
clap is simple, efficient and widely used by the community.
The version used is still in beta (Version 3) but since it has non-backward compatible changes, and several useful upgrades; it might be worthwhile to use the beta until a stable version 3 is released.
clap configuration code can be found in
rust-starter tries to follow the best practices to handle errors. For this, it is useful that your program uses Rust's
std::error::Error trait. All your errors should implement this trait. With the 1.0 release,
rust-starter uses the failure crate; which is now deprecated. thiserror will be used instead in the future; see the note below.
To be able to propagate errors using the
? operator, it's possible to wrap your custom error type with a Box type. This has the downside of dynamically allocating memory for errors in the heap. A better approach is to convert errors at compile time; which
rust-starter has a few examples of.
The approach taken is to define proper
Error types. This has the advantage of easy upgrades and library changes. For example, if you want to switch from the
thiserror crate, you have a central and single place to do this change, and the rest of your code is unchanged.
To test that our error reporting is functioning correctly,
rust-starter has a special subcommand to intentionally trigger an error.
cargo run error
rust-starter uses the better-panic crate to print and prettify backtraces. This library is only enabled when debugging and disabled for release builds.
Backtracing for the
std::Error is only available in nightly. For this reason, the stable
rust-starter still uses the Failure crate. If you want to use
std::Error with Backtrace in nightly, use the
rust-starter manages a configuration struct to mutate, store and retrieve a configuration state. Currently, a configuration file could be passed using the
-c flag, and its content will be merged. Environment variables starting with
APP will also be merged. It's recommended to change the
Under the hood,
rust-starter uses the config-rs crate. However, it exposes an
AppConfig struct that you can use to store and retrieve configuration. The relevant code can be found in
utils/src/app_config.rs. It's recommended to use this struct instead of
config-rs directly, as this depedency might get changed in the future.
The configuration struct is initialized with a default configuration file at program start. This file can be found in
src/resources/default_config.toml. You only need to initialize the configuration once. It's stored in a static RwLock making it globally accessible and also thread-safe.
let config_contents = include_str!("resources/default_config.toml"); AppConfig::init(Some(config_contents))?;
You can merge additional settings to your configuration struct, but also retrieve or change single settings.
// Merge config AppConfig::merge_config(cli_matches.value_of("config"))?; // Get config value AppConfig::get::
("debug").unwrap(); // Set config value AppConfig::set("database.url", "new url").unwrap();
The standard interface for logging in Rust is the log crate. It defines a set of macros for logging like
rust-starter uses slog and has two drains for logs: syslog and terminal; it is fully compatible with the log facade.
rust-starter works out of the box. In any of the sub-crates in your workspace, you can add the log crate as a depedency and use its macros. These logs will be forwarded to slog drains. If these drains are not available or fail to initialize, the logs will be discarded.
To see logging in action, you can run the
error command. It should log an error message to the terminal and syslog. Before the program fails, you should see this line. (This should also be logged to syslog).
Nov 10 01:19:42.014 INFO We are simulating an error, who: rust-starter
While this is good enough, you might want to customize your logging drains. Any logs that you write, are passed to all of these drains. slog supports several drain options. The file
utils/src/logger.rs contains these implementations.
rust-starter comes with a few tests for the commandline program and the config struct. You can run all the tests by running.
cargo test --all
It is recommended to put integration tests for the command line in the root of your program, and write tests for each sub-crate in your workspace individually.
rust-starter also has integrations to run tests in Github actions, and also a code coverage integration with codecov.
rust-starter is not optimized for any particular use-case; and should, preferrably, run in multiple operating systems under different conditions. Unfortunately, it's currently compiled only against Linux. macOS and Windows are high in the list of the OSes to be supported in the next releases.
rust-starter compiles under rust-musl-builder.
rust-musl-builder is a docker image to compile your rust application into a static Rust binary. It is then tested under Alpine Linux to make sure your program is working inside the lightest of containers.
While compiling locally is faster for development, this doesn't give many garantuees about your program running under different conditions. This is less important if you are deploying your program to a predictable environment (ie: a server). You can, then, change the Docker file to match the environment for your deployment.
On the other hand, if you are distributing the program under different conditions as a binary, it might be a good idea to have it compile as a static standalone binary. To do that, all you have to run is the compile command for that. You'll need to have Docker and just installed in your system.
A docker image is created under the name of
name:version. If you didn't change the default values, it should be
rust-starter:1.0.0. To run this image, you can execute.
docker run rust-starter:1.0.0
If you have a Docker hub account, you can push your image to the docker hub cloud. First, you should edit the
dockerhub_org variable in the
justfile and then execute the push command.
Several workflows are included. Some workflows require configuration, while some others could work out of the box.
cargo-generate is a developer tool to help you get up and running quickly with a new Rust project by leveraging a pre-existing git repository as a template. cargo-generate doesn't have any templates by default. A template for rust-starter is available at rust-starter-generate.
cargo generate --git https://github.com/rust-starter/rust-starter-generate
We welcome any kind of contributions. Whether you are reporting a bug, coding a feature or correcting a typo. Every effort counts; and all contributions are greatly appreaciated.
Details on how to contribute can be found in CONTRIBUTING.md.
rust-starter is licensed under the MIT License. Dependent libraries and crates have their own license. An analyze of licensing for these libraries is still under-work.
The logo is sourced from Flaticon.
rust-starter is built and maintained by Abid Omar.
You can reach me at .