diff --git a/src/commands/account.rs b/src/commands/account.rs
index 0d5add6c2d0ea9993a1db3f7888acaa94bad4f40..eab3ceb3d8d8cc0fece69cf4c2f88d2f01ad4d72 100644
--- a/src/commands/account.rs
+++ b/src/commands/account.rs
@@ -28,7 +28,7 @@ pub enum Subcommand {
 
 /// handle account commands
 pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
-	let mut data = data.build_client().await?.build_indexer().await?;
+	let mut data = data.build_client().await?;
 	match command {
 		Subcommand::Balance => {
 			data = data
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index 49670f1a339cd8961c6637ff68a54051c3ceafa0..01525bbe3c176668c5b9d7bd536f16adf92db2a8 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -3,23 +3,25 @@ use crate::*;
 use std::ops::Deref;
 
 type SessionKeys = [u8; 128];
+#[cfg(feature = "gdev")]
+type SmithMembershipMetaData = runtime::runtime_types::common_runtime::entities::SmithMembershipMetaData::<SessionKeys>;
 
 /// define smith subcommands
 #[derive(Clone, Default, Debug, clap::Parser)]
 pub enum Subcommand {
+	/// Request smith membership
+	Request { endpoint: String },
 	/// Emit a smith certification
 	Cert { to: u32 },
 	/// go online
 	GoOnline,
-	#[default]
 	/// go offline
+	#[default]
 	GoOffline,
 	/// Rotate and set session keys
 	UpdateKeys,
 	/// set sudo keys
-	SudoSetKey {
-		new_key: AccountId,
-	},
+	SudoSetKey { new_key: AccountId },
 	/// List upcoming expirations that require an action
 	ShowExpire {
 		/// Show certs that expire within less than this number of blocks
@@ -35,32 +37,36 @@ pub enum Subcommand {
 
 /// handle smith commands
 pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
-	let mut data = data.build_client().await?.build_indexer().await?;
+	let mut data = data.build_client().await?;
 	match command {
+		Subcommand::Request { endpoint } => {
+			data = data.build_keypair();
+			dbg!(request_smith_membership(&data, endpoint).await)?;
+		}
 		Subcommand::GoOnline => {
-			commands::smith::go_online(&data).await?;
+			go_online(&data).await?;
 		}
 		Subcommand::GoOffline => {
-			commands::smith::go_offline(&data).await?;
+			go_offline(&data).await?;
 		}
 		Subcommand::Cert { to } => {
 			data = data.build_keypair().fetch_idty_index().await?;
-			commands::smith::cert(&data, to).await?
+			cert(&data, to).await?
 		}
 		Subcommand::UpdateKeys => {
-			commands::smith::update_session_keys(&data).await?;
+			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?;
+			data = data.build_client().await?.build_indexer().await?;
 			commands::expire::monitor_expirations(&data, blocks, sessions).await?
 		}
 		Subcommand::ShowOnline => {
 			data = data.build_client().await?;
-			commands::smith::online(&data).await?
+			online(&data).await?
 		}
 	};
 
@@ -68,16 +74,45 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 }
 
 /// rotate session keys
+/// (needs to be connected to unsafe RPC)
 pub async fn rotate_keys(client: &Client) -> Result<SessionKeys, anyhow::Error> {
 	client
 		.rpc()
 		.rotate_keys()
-		.await?
+		.await.map_err(|e| anyhow!("Please make sure you are connected to your validator node with the unsafe RPC API enabled {e}"))?
 		.deref()
 		.try_into()
 		.map_err(|e| anyhow!("Session keys have wrong length: {:?}", e))
 }
 
+/// request smith membership
+pub async fn request_smith_membership(data: &Data, endpoint: String) -> Result<(), anyhow::Error> {
+	let session_keys = rotate_keys(data.client()).await?;
+	let metadata =
+		SmithMembershipMetaData {
+			session_keys,
+			owner_key: data.address(),
+			p2p_endpoint: endpoint,
+		};
+	let progress = data
+		.client()
+		.tx()
+		.sign_and_submit_then_watch(
+			&runtime::tx()
+				.smith_membership()
+				.request_membership(metadata),
+			&PairSigner::new(data.keypair()),
+			BaseExtrinsicParamsBuilder::new(),
+		)
+		.await?;
+	let events = track_progress(progress).await?;
+	let request = events.find_first::<runtime::smith_membership::events::MembershipRequested>()?;
+	if let Some(event) = request {
+		println!("{event:?}");
+	}
+	Ok(())
+}
+
 /// set session keys
 pub async fn set_session_keys(
 	data: &Data,
@@ -121,7 +156,8 @@ pub async fn go_online(data: &Data) -> Result<(), GcliError> {
 		));
 	}
 
-	let progress = data.client()
+	let progress = data
+		.client()
 		.tx()
 		.sign_and_submit_then_watch(
 			&runtime::tx().authority_members().go_online(),
@@ -243,7 +279,9 @@ pub async fn cert(data: &Data, receiver: u32) -> Result<(), anyhow::Error> {
 		.client()
 		.tx()
 		.sign_and_submit_then_watch(
-			&runtime::tx().smith_cert().add_cert(data.idty_index(), receiver),
+			&runtime::tx()
+				.smith_cert()
+				.add_cert(data.idty_index(), receiver),
 			&PairSigner::new(data.keypair()),
 			BaseExtrinsicParamsBuilder::new(),
 		)
diff --git a/src/commands/ud.rs b/src/commands/ud.rs
index 0467c3478d70a5143c7cc4c55588b34f59cb412b..6eccdd37d92d0da43953c5af4246d74e2208f589 100644
--- a/src/commands/ud.rs
+++ b/src/commands/ud.rs
@@ -5,7 +5,7 @@ use crate::*;
 pub enum Subcommand {
 	#[default]
 	/// Claim uds
-	ClaimUds,
+	Claim,
 }
 
 /// handle ud commands
@@ -14,7 +14,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 	let mut data = data.build_client().await?;
 	// match subcommand
 	match command {
-		Subcommand::ClaimUds => {
+		Subcommand::Claim => {
 			data = data.build_keypair();
 			claim_ud(data).await?;
 		}