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