diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs
index fb6d2bf1..d6946b4e 100644
--- a/src/admin/user/commands.rs
+++ b/src/admin/user/commands.rs
@@ -1,7 +1,11 @@
 use std::{collections::BTreeMap, fmt::Write as _};
 
 use api::client::{full_user_deactivate, join_room_by_id_helper, leave_room};
-use conduit::{error, info, is_equal_to, utils, warn, PduBuilder, Result};
+use conduit::{
+	debug_warn, error, info, is_equal_to,
+	utils::{self, ReadyExt},
+	warn, PduBuilder, Result,
+};
 use conduit_api::client::{leave_all_rooms, update_avatar_url, update_displayname};
 use futures::StreamExt;
 use ruma::{
@@ -376,6 +380,139 @@ pub(super) async fn list_joined_rooms(&self, user_id: String) -> Result<RoomMess
 	Ok(RoomMessageEventContent::notice_markdown(output_plain))
 }
 
+#[admin_command]
+pub(super) async fn force_join_list_of_local_users(
+	&self, room_id: OwnedRoomOrAliasId, yes_i_want_to_do_this: bool,
+) -> Result<RoomMessageEventContent> {
+	const REASON: &str = "Bulk force joining this room as initiated by the server admin.";
+
+	if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
+	{
+		return Ok(RoomMessageEventContent::text_plain(
+			"Expected code block in command body. Add --help for details.",
+		));
+	}
+
+	if !yes_i_want_to_do_this {
+		return Ok(RoomMessageEventContent::notice_markdown(
+			"You must pass the --yes-i-want-to-do-this-flag to ensure you really want to force bulk join all \
+			 specified local users.",
+		));
+	}
+
+	let Ok(admin_room) = self.services.admin.get_admin_room().await else {
+		return Ok(RoomMessageEventContent::notice_markdown(
+			"There is not an admin room to check for server admins.",
+		));
+	};
+
+	let (room_id, servers) = self
+		.services
+		.rooms
+		.alias
+		.resolve_with_servers(&room_id, None)
+		.await?;
+
+	if !self
+		.services
+		.rooms
+		.state_cache
+		.server_in_room(self.services.globals.server_name(), &room_id)
+		.await
+	{
+		return Ok(RoomMessageEventContent::notice_markdown("We are not joined in this room."));
+	}
+
+	let server_admins: Vec<_> = self
+		.services
+		.rooms
+		.state_cache
+		.active_local_users_in_room(&admin_room)
+		.map(ToOwned::to_owned)
+		.collect()
+		.await;
+
+	if !self
+		.services
+		.rooms
+		.state_cache
+		.room_members(&room_id)
+		.ready_any(|user_id| server_admins.contains(&user_id.to_owned()))
+		.await
+	{
+		return Ok(RoomMessageEventContent::notice_markdown(
+			"There is not a single server admin in the room.",
+		));
+	}
+
+	let usernames = self
+		.body
+		.to_vec()
+		.drain(1..self.body.len().saturating_sub(1))
+		.collect::<Vec<_>>();
+
+	let mut user_ids: Vec<OwnedUserId> = Vec::with_capacity(usernames.len());
+
+	for username in usernames {
+		match parse_active_local_user_id(self.services, username).await {
+			Ok(user_id) => {
+				// don't make the server service account join
+				if user_id == self.services.globals.server_user {
+					self.services
+						.admin
+						.send_message(RoomMessageEventContent::text_plain(format!(
+							"{username} is the server service account, skipping over"
+						)))
+						.await
+						.ok();
+					continue;
+				}
+
+				user_ids.push(user_id);
+			},
+			Err(e) => {
+				self.services
+					.admin
+					.send_message(RoomMessageEventContent::text_plain(format!(
+						"{username} is not a valid username, skipping over: {e}"
+					)))
+					.await
+					.ok();
+				continue;
+			},
+		}
+	}
+
+	let mut failed_joins: usize = 0;
+	let mut successful_joins: usize = 0;
+
+	for user_id in user_ids {
+		match join_room_by_id_helper(
+			self.services,
+			&user_id,
+			&room_id,
+			Some(String::from(REASON)),
+			&servers,
+			None,
+			&None,
+		)
+		.await
+		{
+			Ok(_res) => {
+				successful_joins = successful_joins.saturating_add(1);
+			},
+			Err(e) => {
+				debug_warn!("Failed force joining {user_id} to {room_id} during bulk join: {e}");
+				failed_joins = failed_joins.saturating_add(1);
+			},
+		};
+	}
+
+	Ok(RoomMessageEventContent::notice_markdown(format!(
+		"{successful_joins} local users have been joined to {room_id}. {failed_joins} joins failed.",
+	)))
+}
+
 #[admin_command]
 pub(super) async fn force_join_room(
 	&self, user_id: String, room_id: OwnedRoomOrAliasId,
diff --git a/src/admin/user/mod.rs b/src/admin/user/mod.rs
index e7bb5c73..e1568269 100644
--- a/src/admin/user/mod.rs
+++ b/src/admin/user/mod.rs
@@ -124,4 +124,19 @@ pub(super) enum UserCommand {
 	RedactEvent {
 		event_id: Box<EventId>,
 	},
+
+	/// - Force joins a specified list of local users to join the specified
+	///   room.
+	///
+	/// Specify a codeblock of usernames.
+	///
+	/// At least 1 server admin must be in the room to prevent abuse.
+	///
+	/// Requires the `--yes-i-want-to-do-this` flag.
+	ForceJoinListOfLocalUsers {
+		room_id: OwnedRoomOrAliasId,
+
+		#[arg(long)]
+		yes_i_want_to_do_this: bool,
+	},
 }