Skip to main content

decdn_common/cli/
mod.rs

1//! CLI argument parsing for the `decdn` binary.
2//!
3//! [`RunArgs`] is also re-used (flattened) by [`ConfigValidateArgs`] —
4//! `decdn config validate` runs the same resolver `decdn-node run`
5//! does, against the same `DECDN_*` env vars, without binding ports
6//! or starting any tasks. The daemon's own clap shell lives in
7//! `crates/node/src/main.rs` and is not part of this module.
8
9pub mod appeal;
10pub mod bundle;
11pub mod byte_size;
12pub mod common;
13pub mod config_cmd;
14pub mod fetch;
15pub mod key_gen;
16pub mod node;
17pub mod origin;
18pub mod pool;
19pub mod probe;
20pub mod publish;
21pub mod run;
22pub mod setup;
23pub mod whoami;
24
25pub use appeal::{AppealArgs, AppealCommand, AppealSlashArgs};
26pub use bundle::{BundleArgs, BundleCommand, BundlePullArgs};
27pub use byte_size::parse_byte_size;
28pub use common::{
29    CommonChainArgs, ConfigPathSource, LogFormat, default_client_data_dir, default_config_path,
30    default_data_dir,
31};
32pub use config_cmd::{ConfigArgs, ConfigCommand, ConfigInitArgs, ConfigValidateArgs};
33pub use fetch::{ClientFetchArgs, FetchArgs};
34pub use key_gen::KeyGenArgs;
35pub use node::{
36    BondArgs, ChainArgs, DeregisterArgs, DoctorArgs, DrainArgs, EvictArgs, HealthArgs, LanesArgs,
37    LookupArgs, NodeArgs, NodeCommand, PoolsArgs, RegisterArgs, ReloadArgs, RotateKeyArgs,
38    RotateKeyTarget, SlashesArgs, StatusArgs, TopArgs, UnbondArgs, UpdateMultiaddrsArgs,
39    UpdateRegionArgs,
40};
41pub use origin::{OriginArgs, OriginCommand, OriginImportArgs};
42pub use pool::{
43    PoolArgs, PoolAssignArgs, PoolChainArgs, PoolCloseArgs, PoolCommand, PoolListArgs,
44    PoolOpenArgs, PoolReclaimArgs, PoolTopUpArgs,
45};
46pub use probe::ProbeArgs;
47pub use publish::{
48    AssignArgs, NamespaceArgs, NamespaceCommand, NamespaceCreateArgs, PublishArgs,
49    PublishChainArgs, PublishCommand, RevokeArgs,
50};
51pub use run::RunArgs;
52pub use setup::SetupArgs;
53pub use whoami::WhoamiArgs;
54
55use std::path::PathBuf;
56
57use clap::{Parser, Subcommand};
58
59/// User-facing deCDN CLI. The daemon lives in the separate `decdn-node`
60/// binary; this CLI is what you type from a terminal — probe, fetch, pools,
61/// publishing, node admin.
62#[derive(Parser, Debug)]
63#[command(
64    name = "decdn",
65    version,
66    about = "deCDN user CLI — probe, fetch, pools, publishing, node admin",
67    long_about = "User-facing deCDN CLI. Pairs with the `decdn-node` daemon: \
68                  this binary carries every command a human types in a \
69                  terminal (probe, fetch, payment pools, publishing, \
70                  origin import, node admin, key-gen, config). The \
71                  `node` subcommand group talks to a running daemon over \
72                  the loopback admin RPC surface \
73                  (`appendix-local-admin-http.md`) and fails cleanly on a \
74                  host with no daemon running."
75)]
76pub struct Cli {
77    /// Path to TOML config file [default: ~/.decdn/node.toml].
78    #[arg(long, global = true, value_name = "PATH")]
79    pub config: Option<PathBuf>,
80
81    /// Enable client-side logging at this level. Off by default (the CLI is a
82    /// terminal UI); `RUST_LOG` overrides this when set. Useful for diagnosing
83    /// a stalled `decdn fetch` from the client side. Deliberately not bound to
84    /// an environment variable: the CLI stays silent unless logging is asked
85    /// for on this invocation, even when the daemon's log-level env is exported.
86    #[arg(long, global = true, value_name = "LEVEL")]
87    pub log_level: Option<common::LogLevel>,
88
89    /// Enable client-side logging by count: `-v` is `info`, `-vv` is `debug`,
90    /// `-vvv` is `trace`. Shorthand for `--log-level`, which wins when both are
91    /// given; `RUST_LOG` wins over both.
92    #[arg(short = 'v', long, global = true, action = clap::ArgAction::Count)]
93    pub verbose: u8,
94
95    /// Subcommand to execute.
96    #[command(subcommand)]
97    pub command: Command,
98}
99
100/// Available subcommands. There is intentionally no `run` subcommand —
101/// running the daemon is `decdn-node run` (issue #421). For a dry-run
102/// resolution of the daemon's startup config without binding ports,
103/// see [`ConfigValidateArgs`] (`decdn config validate`), which
104/// flattens the same [`RunArgs`] the daemon parses.
105#[derive(Subcommand, Debug)]
106pub enum Command {
107    /// Generate a new Ed25519 node key and Ethereum keystore.
108    KeyGen(KeyGenArgs),
109    /// Print the local identity read-only: iroh node id, eth address, and the
110    /// resolved key paths. Generates and rotates nothing.
111    Whoami(WhoamiArgs),
112    /// Manage configuration files (`init`, `validate`).
113    Config(ConfigArgs),
114    /// Probe a running node over the `cdn/probe/v1` ALPN.
115    Probe(ProbeArgs),
116    /// Fetch a single content-addressed blob from a node over the paid
117    /// `cdn/client/v1` path, paying per-MB from the caller's own `PaymentPool`
118    /// deposit.
119    Fetch(FetchArgs),
120    /// Guided node onboarding (ADR 019 Phases 1–2): pre-flight checks,
121    /// key generation, bond, and on-chain registration, with a final
122    /// readiness summary. Thin orchestration over `key-gen` / `node bond` /
123    /// `node register` — submits no transaction the primitives don't.
124    Setup(SetupArgs),
125    /// Operator-local admin commands that query a running node
126    /// over its loopback HTTP surface (`appendix-local-admin-http.md`).
127    Node(NodeArgs),
128    /// Fetch directory bundles — a JSON manifest linking
129    /// BLAKE3-content-addressed blobs by relative path. See
130    /// `appendix-bundles.md` for the format.
131    Bundle(BundleArgs),
132    /// Seed a cache origin store from local content (`import`) — offline,
133    /// config-free filesystem work that writes each blob's sharded data object
134    /// and its `{hex}.obao4` outboard in the layout the daemon reads (ADR 037).
135    Origin(OriginArgs),
136    /// Client-side payment-pool lifecycle (`list`/`status`, `open`, `top-up`,
137    /// `close`, `reclaim`, `assign`).
138    Pool(PoolArgs),
139    /// Publisher control plane: create namespaces, and seat or unseat
140    /// authorized origins on-chain (issues #1029 / #1491).
141    /// Content is bound to a namespace off-chain at fetch time, so there is no
142    /// per-hash on-chain claim.
143    Publish(PublishArgs),
144    /// File a slash appeal, posting the appeal bond (ADR 028).
145    Appeal(AppealArgs),
146}
147
148#[cfg(test)]
149mod tests;