CLI app for developers prototyping atproto functionality
1//! Root clap parser and dispatch entry point.
2
3// pattern: Imperative Shell
4
5use clap::Parser;
6use miette::Result;
7use std::process::ExitCode;
8use tracing_subscriber::{EnvFilter, fmt};
9
10use crate::commands::Command;
11use crate::common::diagnostics::install_miette_handler;
12
13/// Top-level `atproto-devtool` CLI.
14#[derive(Debug, Parser)]
15#[command(
16 name = "atproto-devtool",
17 version,
18 about = "Diagnostics and conformance tooling for atproto services.",
19 long_about = None,
20)]
21struct Cli {
22 /// Enable verbose (DEBUG-level) logging to stderr.
23 #[arg(long, global = true)]
24 verbose: bool,
25
26 /// Disable ANSI color in rendered diagnostics.
27 #[arg(long, global = true)]
28 no_color: bool,
29
30 #[command(subcommand)]
31 command: Command,
32}
33
34/// Parse `std::env::args()`, install global handlers, and dispatch.
35///
36/// Returns `Result<ExitCode, miette::Report>` to propagate exit codes through
37/// the dispatch chain. The main handler renders errors with exit code 1.
38pub async fn run() -> Result<ExitCode> {
39 let cli = Cli::parse();
40
41 // Check NO_COLOR environment variable in addition to --no-color flag.
42 // NO_COLOR takes effect if present and non-empty, per https://no-color.org/
43 let no_color = cli.no_color || std::env::var("NO_COLOR").is_ok();
44
45 install_miette_handler(no_color)?;
46 install_tracing(cli.verbose);
47
48 cli.command.run(no_color).await
49}
50
51fn install_tracing(verbose: bool) {
52 let default_filter = if verbose { "debug" } else { "warn" };
53 let filter =
54 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(default_filter));
55
56 let _ = fmt()
57 .with_env_filter(filter)
58 .with_writer(std::io::stderr)
59 .try_init();
60}