Every serious CLI tool deserves tab completions. bdk-cli finally got them.

The missing piece

cargo has tab completions. rustup has tab completions. Even git has tab completions. But bdk-cli? Nope. You had to remember every subcommand and flag by heart, or keep running --help. For a project that aims to be a proper developer tool, that felt like an oversight.

Tab completions aren't just a nice-to-have - they genuinely improve UX. Less typing, fewer typos, faster exploration of available commands. Time to fix this.

The approach

Rustup uses clap_complete - a companion crate to clap that generates shell completion scripts for bash, zsh, fish, powershell, and elvish. Since bdk-cli already uses clap for argument parsing, adding clap_complete is a natural fit.

The idea is simple: add a completions subcommand that spits out a completion script for your shell. You run it once, source the output, and you're done.

Implementation

The core is a single function call:

use clap::CommandFactory;
use clap_complete::{generate, Shell};

fn print_completions(shell: Shell) {
    generate(
        shell,
        &mut CliOpts::command(),
        "bdk-cli",
        &mut std::io::stdout(),
    );
}

clap_complete::generate takes the shell type, a reference to the clap Command, the binary name, and a writer. It introspects the command tree and produces a completion script that knows about all subcommands, flags, and arguments.

The completions subcommand itself:

/// Generate shell completion scripts
Completions {
    /// Target shell
    shell: Shell,
},

Shell implements ValueEnum, so clap handles parsing and validation for free.

Usage

% bdk-cli completions bash > ~/.bash_completions/bdk-cli
% source ~/.bash_completions/bdk-cli
% bdk-cli <TAB>
compile  wallet  key  repl  completions

For zsh, fish, and others - same idea, different output format.