diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index 12ea71cd63d47c446d1dc198bc78e66a82ce5c78..929ea03f4a1f6c0e1761ff8cbcc5e877f681de64 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -1,4 +1,4 @@
-use crate::{gdev, Client};
+use crate::{cache, gdev, indexer::*, Args, Client};
 
 use anyhow::{anyhow, Result};
 use sp_core::{crypto::AccountId32, sr25519::Pair, Pair as _};
@@ -76,3 +76,89 @@ pub async fn go_offline(pair: Pair, client: Client) -> Result<()> {
 
     Ok(())
 }
+
+pub async fn online(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 mut identity_cache = cache::IdentityCache::new(
+        &client,
+        if args.no_indexer {
+            None
+        } else {
+            Some(Indexer {
+                gql_client,
+                gql_url: &args.indexer,
+            })
+        },
+    );
+
+    let online_authorities = client
+        .storage()
+        .fetch(
+            &gdev::storage().authority_members().online_authorities(),
+            Some(parent_hash),
+        )
+        .await?
+        .unwrap_or_default();
+
+    println!("Online:");
+    for identity_id in online_authorities {
+        println!(
+            "  {}",
+            identity_cache
+                .fetch_identity(identity_id, parent_hash)
+                .await
+                .unwrap_or_else(|_| format!("{identity_id}"))
+        );
+    }
+
+    let incoming_authorities = client
+        .storage()
+        .fetch(
+            &gdev::storage().authority_members().incoming_authorities(),
+            Some(parent_hash),
+        )
+        .await?
+        .unwrap_or_default();
+
+    println!("Incoming:");
+    for identity_id in incoming_authorities {
+        println!(
+            "  {}",
+            identity_cache
+                .fetch_identity(identity_id, parent_hash)
+                .await
+                .unwrap_or_else(|_| format!("{identity_id}"))
+        );
+    }
+
+    let outgoing_authorities = client
+        .storage()
+        .fetch(
+            &gdev::storage().authority_members().outgoing_authorities(),
+            Some(parent_hash),
+        )
+        .await?
+        .unwrap_or_default();
+
+    println!("Outgoing:");
+    for identity_id in outgoing_authorities {
+        println!(
+            "  {}",
+            identity_cache
+                .fetch_identity(identity_id, parent_hash)
+                .await
+                .unwrap_or_else(|_| format!("{identity_id}"))
+        );
+    }
+
+    Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index 1f7ff54826fb1de43ec31864dc773d806fabeb2b..e741ac9c5b55f5e0d7f2cbfe5279c898747aaebf 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -123,6 +123,8 @@ pub enum Subcommand {
     OneshotBalance {
         account: sp_core::crypto::AccountId32,
     },
+    /// List online authorities
+    Online,
     #[clap(hide = true)]
     Repart {
         // Number of transactions per block to target
@@ -280,6 +282,7 @@ async fn main() -> Result<()> {
         Subcommand::OneshotBalance { account } => {
             commands::oneshot::oneshot_account_balance(client, account).await?
         }
+        Subcommand::Online => commands::smith::online(client, &args).await?,
         Subcommand::Repart {
             target,
             actual_repart,