diff --git a/src/commands.rs b/src/commands.rs
index 976ef714690268c6c67d8aefa5268c44f7aaeeb5..f419bf31866d46b3a4c0c9d4a919847b8257b869 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -1,3 +1,4 @@
+pub mod collective;
 pub mod expire;
 pub mod identity;
 pub mod net_test;
diff --git a/src/commands/collective.rs b/src/commands/collective.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5fa99dd8c4cc30a11956d1d02b70b6bfbe222021
--- /dev/null
+++ b/src/commands/collective.rs
@@ -0,0 +1,59 @@
+use crate::{gdev, indexer::*, Args, Client};
+
+use anyhow::Result;
+
+pub async fn technical_committee_members(client: Client, args: &Args) -> Result<()> {
+    let parent_hash = client
+        .storage()
+        .fetch(&gdev::storage().system().parent_hash(), None)
+        .await?
+        .unwrap();
+
+    let gql_client = reqwest::Client::builder()
+        .user_agent("gcli/0.1.0")
+        .build()?;
+
+    let indexer = if args.no_indexer {
+        None
+    } else {
+        Some(Indexer {
+            gql_client,
+            gql_url: &args.indexer,
+        })
+    };
+
+    for account_id in client
+        .storage()
+        .fetch(
+            &gdev::storage().technical_committee().members(),
+            Some(parent_hash),
+        )
+        .await?
+        .unwrap_or_default()
+    {
+        println!(
+            "{}",
+            if let Some(indexer) = &indexer {
+                indexer
+                    .username_by_pubkey(&account_id.to_string())
+                    .await
+                    .ok()
+                    .flatten()
+            } else {
+                client
+                    .storage()
+                    .fetch(
+                        &gdev::storage().identity().identity_index_of(&account_id),
+                        Some(parent_hash),
+                    )
+                    .await
+                    .ok()
+                    .flatten()
+                    .map(|identity_id| format!("{identity_id}"))
+            }
+            .unwrap_or_else(|| account_id.to_string(),)
+        );
+    }
+
+    Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index e741ac9c5b55f5e0d7f2cbfe5279c898747aaebf..a7cb40b6c13b0f5d59c933bbd6c515165dccada4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -140,6 +140,8 @@ pub enum Subcommand {
     SudoSetKey {
         new_key: sp_core::crypto::AccountId32,
     },
+    /// List members of the technical committee
+    TechMembers,
     Transfer {
         /// Amount to transfer
         amount: u64,
@@ -311,6 +313,9 @@ async fn main() -> Result<()> {
             )
             .await?
         }
+        Subcommand::TechMembers => {
+            commands::collective::technical_committee_members(client, &args).await?
+        }
         Subcommand::Transfer {
             amount,
             dest,