Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ All notable changes to this project will be documented in this file.
- Add `docs/cli-standard.md`, the contributor-facing summary of RFC-20 with the `location get` worked example and pointers to the shared validators, formatters, logging facade, and test helpers in `doublezero-cli-core`.
- Update `CLAUDE.md` with a CLI-standard section pointing at RFC-20, the contributor doc, and the reference verb so future contributors land on the standard quickly.
- Move the per-resource serviceability subcommand wrapper files (`accesspass`, `config`, `contributor`, `device`, `exchange`, `globalconfig`, `link`, `location`, `multicastgroup`, `permission`, `resource`, `tenant`, `user`) from `client/doublezero/src/cli/` into the module crate at `smartcontract/cli/src/cli/` per RFC-20 §Module contract item 2. Internal imports in the moved files switch from `doublezero_serviceability_cli::<resource>::*` to `crate::<resource>::*`. Binary import paths in `client/doublezero/src/{cli/command.rs,main.rs}` switch to `doublezero_serviceability_cli::cli::<resource>::*`. `cli/multicast.rs` stays in the binary because its `Subscribe`/`Unsubscribe`/`Publish`/`Unpublish` variants are async and depend on binary-local daemon-control infrastructure (`ServiceControllerImpl`, `crate::command::helpers::resolve_client_ip`); the binary now imports `MulticastGroupCliCommand` from the library.
- Introduce `doublezero_serviceability_cli::cli::ServiceabilityCommand`, the module crate's top-level subcommand enum + `async fn execute(ctx, client, out)` dispatcher per RFC-20 §Module contract item 2. Aggregates 17 serviceability variants (`Init`, `Migrate`, `Address`, `Balance`, `Config`, `GlobalConfig`, `Location`, `Exchange`, `Contributor`, `Permission`, `Tenant`, `Device`, `Link`, `AccessPass`, `User`, `Export`, `Keygen`, `Resource`) and owns the full dispatch tree currently inlined in `client/doublezero/src/main.rs`. Defined but not yet wired into the unified binary; the next PR adds `#[command(flatten)] Serviceability(ServiceabilityCommand)` to the binary's `Command` enum and collapses `main.rs` to a single dispatch arm. Binary `Command` enum and `main.rs` dispatch are unchanged; this is pure file relocation.
- Introduce `doublezero_serviceability_cli::cli::ServiceabilityCommand`, the module crate's top-level subcommand enum + `async fn execute(ctx, client, out)` dispatcher per RFC-20 §Module contract item 2. Aggregates 17 serviceability variants (`Init`, `Migrate`, `Address`, `Balance`, `Config`, `GlobalConfig`, `Location`, `Exchange`, `Contributor`, `Permission`, `Tenant`, `Device`, `Link`, `AccessPass`, `User`, `Export`, `Keygen`, `Resource`) and owns the full dispatch tree currently inlined in `client/doublezero/src/main.rs`. Defined but not yet wired into the unified binary; the next PR adds `#[command(flatten)] Serviceability(ServiceabilityCommand)` to the binary's `Command` enum and collapses `main.rs` to a single dispatch arm.
- Hoist `ServiceabilityCommand` into the unified `doublezero` binary via `#[command(flatten)]` on the binary's `Command` enum. Drops 17 explicit variants and collapses the `main.rs` dispatch match block from roughly 270 lines to one arm (`Command::Serviceability(cmd) => cmd.execute(&ctx, &client, &mut handle).await`). The binary retains daemon-control verbs (`Connect`, `Enable`, `Disable`, `Status`, `Disconnect`, `Latency`, `Routes`), raw-`DZClient` diagnostics (`Account`, `Accounts`, `Log`), the binary-local geolocation tree, `InitGeolocationConfig`, the multicast dispatch (whose `Subscribe`/`Unsubscribe`/`Publish`/`Unpublish` async arms depend on daemon-control infrastructure), and the `Completion` generator. User-facing `doublezero --help` is byte-identical to the pre-refactor output (29 visible top-level commands); no flag, name, or output change. Binary `Command` enum and `main.rs` dispatch are unchanged; this is pure file relocation.
- Move `MulticastGroupCommands` dispatch out of `client/doublezero/src/main.rs` and into a `pub fn execute(&client, &mut out)` method on the enum itself, defined next to the enum in `smartcontract/cli/src/cli/multicastgroup.rs`. Mirrors the per-resource dispatch pattern in `ServiceabilityCommand::execute` and finishes the flatten/collapse work for the one module-crate subtree reached through the binary's `MulticastCliCommand` wrapper (which has to stay binary-local because its `Subscribe`/`Unsubscribe`/`Publish`/`Unpublish` arms depend on `ServiceControllerImpl`). The binary's `Multicast` arm shrinks from a 5-level nested match (Allowlist → Publisher/Subscriber → Add/Remove/List, plus Create/Update/List/Get/Delete at the Group level) to `MulticastCommands::Group(args) => args.command.execute(&client, &mut handle)`. No flag, name, or user-facing output change.

## [v0.24.0](https://github.com/malbeclabs/doublezero/compare/client/v0.23.0...client/v0.24.0) - 2026-05-22

Expand Down
120 changes: 30 additions & 90 deletions client/doublezero/src/cli/command.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
use clap::{Args, Subcommand};
use clap_complete::Shell;
use doublezero_serviceability_cli::{
account::GetAccountCliCommand, accounts::GetAccountsCliCommand, cli::ServiceabilityCommand,
geolocation::programconfig::init::InitProgramConfigCliCommand, logcommand::LogCliCommand,
};

use crate::{
cli::{geolocation::GeolocationCliCommand, multicast::MulticastCliCommand},
command::{
Expand All @@ -6,124 +13,57 @@ use crate::{
latency::LatencyCliCommand, routes::RoutesCliCommand, status::StatusCliCommand,
},
};
use clap::{Args, Subcommand};
use clap_complete::Shell;
use doublezero_serviceability_cli::{
account::GetAccountCliCommand,
accounts::GetAccountsCliCommand,
address::AddressCliCommand,
balance::BalanceCliCommand,
cli::{
accesspass::AccessPassCliCommand, config::ConfigCliCommand,
contributor::ContributorCliCommand, device::DeviceCliCommand, exchange::ExchangeCliCommand,
globalconfig::GlobalConfigCliCommand, link::LinkCliCommand, location::LocationCliCommand,
permission::PermissionCliCommand, resource::ResourceCliCommand, tenant::TenantCliCommand,
user::UserCliCommand,
},
export::ExportCliCommand,
geolocation::programconfig::init::InitProgramConfigCliCommand,
init::InitCliCommand,
keygen::KeyGenCliCommand,
logcommand::LogCliCommand,
migrate::MigrateCliCommand,
};

/// Top-level command tree for the unified `doublezero` binary.
///
/// Per RFC-20 §Module contract item 2, the serviceability verbs live in
/// `doublezero_serviceability_cli::cli::ServiceabilityCommand` and are hoisted
/// to the top level here via `#[command(flatten)]`. The binary retains the
/// daemon-control verbs, the binary-local geolocation tree, the raw-`DZClient`
/// diagnostics (`Account`, `Accounts`, `Log`), the geolocation program-config
/// init, the binary-only `Completion` generator, and `Multicast` (whose
/// `Subscribe`/`Unsubscribe`/`Publish`/`Unpublish` arms depend on binary-local
/// daemon-control infrastructure).
#[derive(Subcommand, Debug)]
pub enum Command {
#[command(hide = true)]
Init(InitCliCommand),
#[command(hide = true)]
Migrate(MigrateCliCommand),
#[command(hide = true)]
InitGeolocationConfig(InitProgramConfigCliCommand),
/// Connect your server to a doublezero device
#[command()]
Connect(ProvisioningCliCommand),
/// Enable the reconciler (start managing tunnels)
#[command()]
Enable(EnableCliCommand),
/// Disable the reconciler (tear down tunnels and stop managing them)
#[command()]
Disable(DisableCliCommand),
/// Get the status of your service
#[command()]
Status(StatusCliCommand),
/// Disconnect your server from the doublezero network
#[command()]
Disconnect(DecommissioningCliCommand),
/// Get device latencies
#[command()]
Latency(LatencyCliCommand),
/// View your installed routes
#[command()]
Routes(RoutesCliCommand),
/// Get your public key
#[command()]
Address(AddressCliCommand),
/// Get your balance
#[command()]
Balance(BalanceCliCommand),
/// local configuration
#[command()]
Config(ConfigCliCommand),
/// Global network configuration
#[command()]
GlobalConfig(GlobalConfigCliCommand),

/// Get Account
#[command()]
Account(GetAccountCliCommand),
/// List Accounts
#[command(hide = true)]
Accounts(GetAccountsCliCommand),
/// Manage locations
#[command()]
Location(LocationCliCommand),
/// Manage exchanges
#[command()]
Exchange(ExchangeCliCommand),
/// Manage contributors
#[command()]
Contributor(ContributorCliCommand),
/// Manage permissions
#[clap()]
Permission(PermissionCliCommand),
/// Manage tenants
#[command()]
Tenant(TenantCliCommand),
/// Manage devices
#[command()]
Device(DeviceCliCommand),
/// Manage tunnels between devices
#[command()]
Link(LinkCliCommand),
/// Get logs
Log(LogCliCommand),

#[command()]
AccessPass(AccessPassCliCommand),
#[command(hide = true)]
InitGeolocationConfig(InitProgramConfigCliCommand),
/// Manage geolocation probes and users
Geolocation(GeolocationCliCommand),

/// Manage users
#[command()]
User(UserCliCommand),
/// Manage multicast
#[command()]
Multicast(MulticastCliCommand),
/// Manage geolocation probes and users
#[command()]
Geolocation(GeolocationCliCommand),
/// Export all data to files
#[command()]
Export(ExportCliCommand),
/// Create a new user identity
#[command()]
Keygen(KeyGenCliCommand),
/// Get logs
#[command()]
Log(LogCliCommand),

/// Generate shell completions
#[command()]
Completion(CompletionCliCommand),
/// IP/ID Resource Management
#[command()]
Resource(ResourceCliCommand),

/// Flattened serviceability variants (Device, Link, Location, User, ...).
/// Hoisted to top-level via `#[command(flatten)]`.
#[command(flatten)]
Serviceability(ServiceabilityCommand),
}

#[derive(Args, Debug, Clone)]
Expand Down
Loading
Loading