Shell Completions & Man Pages
Generate shell completions and man pages directly from your clap definitions so docs never drift.
Search across all documentation pages
Generate shell completions and man pages directly from your clap definitions so docs never drift.
# Generate bash completions at build time
cargo add clap_complete --features generatoruse clap::{CommandFactory, Parser};
use clap_complete::{generate, shells::Bash};
use std::io;
#[derive(Parser)]
#[command(name = "mytool")]
struct Cli {}
fn main() {
let mut cmd = Cli::command();
generate(Bash, &mut cmd, "mytool", &mut io::stdout());
}When to reach for this: Any CLI your users install locally and expect to tab-complete like native system tools.
// build.rs
use clap::CommandFactory;
use std::{env, fs, path::PathBuf};
fn main() {
let out = PathBuf::from(env::var("OUT_DIR").unwrap());
let mut cmd = mytool::Cli::command();
for (shell, path) in [
(clap_complete::Shell::Bash, out.join("mytool.bash")),
(clap_complete::Shell::Zsh, out.join("_mytool")),
(clap_complete::Shell::Fish, out.join("mytool.fish")),
] {
let mut file = fs::File::create(&path).unwrap();
clap_complete::generate(shell, &mut cmd, "mytool", &mut file);
}
println!("cargo:rerun-if-changed=src/lib.rs");
}# Install bash completion (example)
sudo cp target/debug/build/mytool-*/out/mytool.bash \
/etc/bash_completion.d/mytoolWhat this demonstrates:
build.rs regenerates completions on every CLI changeParser deriveuse clap_mangen::Man;
let man = Man::new(Cli::command());
man.render(&mut std::io::stdout())?;Install to share/man/man1/mytool.1 in your packaging pipeline.
| Artifact | Target path |
|---|---|
| Bash completion | /etc/bash_completion.d/mytool |
| Zsh completion | _mytool in $fpath |
| Man page | share/man/man1/mytool.1 |
mytool completions bash subcommand prints script for evalgenerate().visible_alias in clap.man 1 mytool in docs.| Alternative | Use When | Don't Use When |
|---|---|---|
| Hand-written completion scripts | Very custom completion logic | Standard flag/subcommand CLIs |
roff man pages by hand | Fine-tuned typography | clap-managed CLIs that change often |
--help only | Internal tools | Public developer-facing CLIs |
Document shell-specific steps in README. Better: include a mytool completions install helper.
Add generated scripts as release assets. cargo-dist can upload them alongside binaries.
clap_complete supports Completer trait for runtime values like filenames. See clap_complete docs.
Zsh expects _<command> with no extension, placed in a directory listed in $fpath.
Generate with Shell::Fish. Copy to ~/.config/fish/completions/mytool.fish.
Snapshot-test generated scripts in CI. Fail the build when output changes unexpectedly.
Section 1 for user commands, section 5 for config file formats.
Man pages work on Linux and macOS. Windows users rely on --help and web docs.
Package managers have hooks for completion install. Follow each formula's conventions.
Regenerate man pages each release so VERSION in the header stays current.
--help fundamentalsStack 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+.
Reviewed by Chris St. John·Last updated Jul 19, 2026