diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index 46df5fe11ce9c46c70fb9bfa6d1943d0092e431e..32b5fc8744396db03c1a712c3482ccf9ed263005 100644
--- a/src/commands/identity.rs
+++ b/src/commands/identity.rs
@@ -33,6 +33,8 @@ pub enum Subcommand {
 	Confirm { name: String },
 	/// Revoke an identity immediately
 	Revoke,
+	/// Generate a revocation document for the provided account
+	GenRevocDoc,
 }
 
 /// handle identity commands
@@ -65,6 +67,13 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 			data = data.build_keypair().fetch_idty_index().await?;
 			commands::identity::revoke_identity(data).await?;
 		}
+		Subcommand::GenRevocDoc => {
+			data = data
+				.build_keypair()
+				.fetch_idty_index()
+				.await?;
+			commands::revocation::print_revoc_sig(&data)
+		}
 	};
 
 	Ok(())
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index bc2fd052dddaa6e5e5161d6b29c165d78e1c6f19..a05f677e28035432e722d211d2a51d0bb97021e7 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -1,11 +1,73 @@
 use crate::*;
 
-use sp_core::{crypto::AccountId32, sr25519::Pair, Pair as _};
 use std::ops::Deref;
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
 type SessionKeys = [u8; 128];
 
+/// define smith subcommands
+#[derive(Clone, Default, Debug, clap::Parser)]
+pub enum Subcommand {
+	/// Emit a smith certification
+	Cert { to: u32 },
+	/// go online
+	GoOnline,
+	#[default]
+	/// go offline
+	GoOffline,
+	/// Rotate and set session keys
+	UpdateKeys,
+	/// set sudo keys
+	SudoSetKey {
+		new_key: AccountId,
+	},
+	/// List upcoming expirations that require an action
+	ShowExpire {
+		/// Show certs that expire within less than this number of blocks
+		#[clap(short, long, default_value_t = 100800)]
+		blocks: u32,
+		/// Show authorities that should rotate keys within less than this number of sessions
+		#[clap(short, long, default_value_t = 100)]
+		sessions: u32,
+	},
+	/// List online authorities
+	ShowOnline,
+}
+
+/// handle smith commands
+pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
+	let mut data = data.build_client().await?.build_indexer().await?;
+	match command {
+		Subcommand::GoOnline => {
+			commands::smith::go_online(&data).await?;
+		}
+		Subcommand::GoOffline => {
+			commands::smith::go_offline(&data).await?;
+		}
+		Subcommand::Cert { to } => {
+			data = data.build_keypair().fetch_idty_index().await?;
+			commands::smith::cert(&data, to).await?
+		}
+		Subcommand::UpdateKeys => {
+			commands::smith::update_session_keys(&data).await?;
+		}
+		Subcommand::SudoSetKey { new_key } => {
+			data = data.build_keypair().build_client().await?;
+			commands::sudo::set_key(data.keypair(), data.client(), new_key).await?;
+		}
+		Subcommand::ShowExpire { blocks, sessions } => {
+			data = data.build_client().await?;
+			commands::expire::monitor_expirations(&data, blocks, sessions).await?
+		}
+		Subcommand::ShowOnline => {
+			data = data.build_client().await?;
+			commands::smith::online(&data).await?
+		}
+	};
+
+	Ok(())
+}
+
 /// rotate session keys
 pub async fn rotate_keys(client: &Client) -> Result<SessionKeys, anyhow::Error> {
 	client
@@ -19,39 +81,37 @@ pub async fn rotate_keys(client: &Client) -> Result<SessionKeys, anyhow::Error>
 
 /// set session keys
 pub async fn set_session_keys(
-	pair: Pair,
-	client: &Client,
+	data: &Data,
 	session_keys: SessionKeys,
 ) -> Result<TxProgress, subxt::Error> {
-	client
+	data.client()
 		.tx()
 		.sign_and_submit_then_watch(
 			&runtime::tx()
 				.authority_members()
 				.set_session_keys(session_keys),
-			&PairSigner::new(pair),
+			&PairSigner::new(data.keypair()),
 			BaseExtrinsicParamsBuilder::new(),
 		)
 		.await
 }
 
 /// update session keys
-pub async fn update_session_keys(pair: Pair, client: &Client) -> Result<(), GcliError> {
-	let session_keys = rotate_keys(client).await?;
-	let progress = set_session_keys(pair, client, session_keys).await?;
+pub async fn update_session_keys(data: &Data) -> Result<(), GcliError> {
+	let session_keys = rotate_keys(data.client()).await?;
+	let progress = set_session_keys(data, session_keys).await?;
 
 	let _ = track_progress(progress).await?; // TODO
 	Ok(())
 }
 
 /// submit go_online
-pub async fn go_online(pair: Pair, client: &Client) -> Result<(), GcliError> {
-	if client
+pub async fn go_online(data: &Data) -> Result<(), GcliError> {
+	if data
+		.client()
 		.storage()
 		.fetch(
-			&runtime::storage()
-				.session()
-				.next_keys(AccountId32::from(pair.public())),
+			&runtime::storage().session().next_keys(data.address()),
 			None,
 		)
 		.await?
@@ -62,11 +122,11 @@ pub async fn go_online(pair: Pair, client: &Client) -> Result<(), GcliError> {
 		));
 	}
 
-	let progress = client
+	let progress = data.client()
 		.tx()
 		.sign_and_submit_then_watch(
 			&runtime::tx().authority_members().go_online(),
-			&PairSigner::new(pair),
+			&PairSigner::new(data.keypair()),
 			BaseExtrinsicParamsBuilder::new(),
 		)
 		.await?;
@@ -79,12 +139,13 @@ pub async fn go_online(pair: Pair, client: &Client) -> Result<(), GcliError> {
 }
 
 /// submit go_offline
-pub async fn go_offline(pair: Pair, client: &Client) -> Result<(), subxt::Error> {
-	let progress = client
+pub async fn go_offline(data: &Data) -> Result<(), subxt::Error> {
+	let progress = data
+		.client()
 		.tx()
 		.sign_and_submit_then_watch(
 			&runtime::tx().authority_members().go_offline(),
-			&PairSigner::new(pair),
+			&PairSigner::new(data.keypair()),
 			BaseExtrinsicParamsBuilder::new(),
 		)
 		.await?;
@@ -178,17 +239,13 @@ pub async fn online(data: &Data) -> Result<(), anyhow::Error> {
 }
 
 /// submit a certification and track progress
-pub async fn cert(
-	client: &Client,
-	pair: Pair,
-	issuer: u32,
-	receiver: u32,
-) -> Result<(), anyhow::Error> {
-	let progress = client
+pub async fn cert(data: &Data, receiver: u32) -> Result<(), anyhow::Error> {
+	let progress = data
+		.client()
 		.tx()
 		.sign_and_submit_then_watch(
-			&runtime::tx().smith_cert().add_cert(issuer, receiver),
-			&PairSigner::new(pair),
+			&runtime::tx().smith_cert().add_cert(data.idty_index(), receiver),
+			&PairSigner::new(data.keypair()),
 			BaseExtrinsicParamsBuilder::new(),
 		)
 		.await?;
diff --git a/src/main.rs b/src/main.rs
index c9000b25c5472054f801db56100dec652ea2090c..896d00149091745cbd7438ce093c5acab3fd6ed2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -162,21 +162,6 @@ pub enum Subcommand {
 	Balance,
 	/// Show address corresponding to given arguments
 	ShowAddress,
-	/// Generate a revocation document for the provided account
-	GenRevocDoc,
-	/// List upcoming expirations that require an action
-	Expire {
-		/// Show certs that expire within less than this number of blocks
-		#[clap(short, long, default_value_t = 100800)]
-		blocks: u32,
-		/// Show authorities that should rotate keys within less than this number of sessions
-		#[clap(short, long, default_value_t = 100)]
-		sessions: u32,
-	},
-	GoOffline,
-	GoOnline,
-	/// List online authorities
-	Online,
 	#[clap(hide = true)]
 	Repart {
 		// Number of transactions per block to target
@@ -189,13 +174,6 @@ pub enum Subcommand {
 	SpamRoll {
 		actual_repart: usize,
 	},
-	SudoSetKey {
-		new_key: AccountId,
-	},
-	/// Emit a smith certification
-	SmithCert {
-		to: u32,
-	},
 	/// List members of the technical committee
 	TechMembers,
 	/// List proposals to the technical committee
@@ -226,21 +204,22 @@ pub enum Subcommand {
 		/// List of target addresses
 		dests: Vec<AccountId>,
 	},
-	/// Rotate and set session keys
-	UpdateKeys,
 	/// Get information about runtime
 	RuntimeInfo,
 	/// Check current block
 	CurrentBlock,
-	/// Indentity subcommands
+	/// Identity subcommands
 	#[clap(subcommand)]
 	Identity(commands::identity::Subcommand),
-	/// Oneshot account subcommands
+	/// Smith subcommands
 	#[clap(subcommand)]
-	Oneshot(commands::oneshot::Subcommand),
+	Smith(commands::smith::Subcommand),
 	/// Universal Dividend subcommands
 	#[clap(subcommand)]
 	Ud(commands::ud::Subcommand),
+	/// Oneshot account subcommands
+	#[clap(subcommand)]
+	Oneshot(commands::oneshot::Subcommand),
 	/// Indexer subcommands
 	#[clap(subcommand)]
 	Indexer(indexer::Subcommand),
@@ -272,53 +251,6 @@ async fn main() -> Result<(), GcliError> {
 			data = data.build_address();
 			println!("address is: {}", data.address());
 		}
-		Subcommand::Expire { blocks, sessions } => {
-			data = data.build_client().await?;
-			commands::expire::monitor_expirations(&data, blocks, sessions).await?
-		}
-		Subcommand::GenRevocDoc => {
-			data = data
-				.build_client()
-				.await?
-				.build_keypair()
-				.fetch_idty_index()
-				.await?;
-			commands::revocation::print_revoc_sig(&data)
-		}
-		Subcommand::GoOffline => {
-			data = data.build_client().await?;
-			commands::smith::go_offline(
-				get_keys(
-					args.secret_format,
-					&args.address,
-					&args.secret,
-					NeededKeys::Secret,
-				)?
-				.1
-				.unwrap(),
-				data.client(),
-			)
-			.await?;
-		}
-		Subcommand::GoOnline => {
-			data = data.build_client().await?;
-			commands::smith::go_online(
-				get_keys(
-					args.secret_format,
-					&args.address,
-					&args.secret,
-					NeededKeys::Secret,
-				)?
-				.1
-				.unwrap(),
-				data.client(),
-			)
-			.await?;
-		}
-		Subcommand::Online => {
-			data = data.build_client().await?;
-			commands::smith::online(&data).await?
-		}
 		Subcommand::Repart {
 			target,
 			actual_repart,
@@ -355,19 +287,6 @@ async fn main() -> Result<(), GcliError> {
 			)
 			.await?
 		}
-		Subcommand::SudoSetKey { new_key } => {
-			data = data.build_keypair().build_client().await?;
-			commands::sudo::set_key(data.keypair(), data.client(), new_key).await?;
-		}
-		Subcommand::SmithCert { to } => {
-			data = data
-				.build_client()
-				.await?
-				.build_keypair()
-				.fetch_idty_index()
-				.await?;
-			commands::smith::cert(data.client(), data.keypair(), data.idty_index(), to).await?
-		}
 		Subcommand::TechMembers => {
 			data = data.build_client().await?;
 			commands::collective::technical_committee_members(&data).await?
@@ -438,21 +357,6 @@ async fn main() -> Result<(), GcliError> {
 			)
 			.await?;
 		}
-		Subcommand::UpdateKeys => {
-			data = data.build_client().await?;
-			commands::smith::update_session_keys(
-				get_keys(
-					args.secret_format,
-					&args.address,
-					&args.secret,
-					NeededKeys::Secret,
-				)?
-				.1
-				.unwrap(),
-				data.client(),
-			)
-			.await?;
-		}
 		Subcommand::RuntimeInfo => {
 			data = data.build_client().await?.fetch_system_properties().await?;
 			commands::runtime::runtime_info(data).await;
@@ -470,10 +374,11 @@ async fn main() -> Result<(), GcliError> {
 			);
 		}
 		Subcommand::Identity(subcommand) => commands::identity::handle_command(data, subcommand).await?,
+		Subcommand::Smith(subcommand) => commands::smith::handle_command(data, subcommand).await?,
+		Subcommand::Ud(subcommand) => commands::ud::handle_command(data, subcommand).await?,
 		Subcommand::Oneshot(subcommand) => {
 			commands::oneshot::handle_command(data, subcommand).await?
 		}
-		Subcommand::Ud(subcommand) => commands::ud::handle_command(data, subcommand).await?,
 		Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand).await?,
 		Subcommand::Config(subcommand) => conf::handle_command(data, subcommand)?,
 	}