diff --git a/substrate/client/cli/src/commands/run_cmd.rs b/substrate/client/cli/src/commands/run_cmd.rs
index 9441acecc4dfc50d58467f7ed32e3f685be1dc81..a38ba6f49e3dd55d16a7f0dfe4dd0ff6634b1e8a 100644
--- a/substrate/client/cli/src/commands/run_cmd.rs
+++ b/substrate/client/cli/src/commands/run_cmd.rs
@@ -23,7 +23,7 @@ use crate::{
 		ImportParams, KeystoreParams, NetworkParams, OffchainWorkerParams, SharedParams,
 		TransactionPoolParams,
 	},
-	CliConfiguration,
+	CliConfiguration, PrometheusParams, RuntimeParams, TelemetryParams,
 };
 use clap::Parser;
 use regex::Regex;
@@ -116,12 +116,6 @@ pub struct RunCmd {
 	#[arg(long)]
 	pub rpc_max_subscriptions_per_connection: Option<usize>,
 
-	/// Expose Prometheus exporter on all interfaces.
-	///
-	/// Default is local.
-	#[arg(long)]
-	pub prometheus_external: bool,
-
 	/// DEPRECATED, IPC support has been removed.
 	#[arg(long, value_name = "PATH")]
 	pub ipc_path: Option<String>,
@@ -151,36 +145,23 @@ pub struct RunCmd {
 	#[arg(long, value_name = "ORIGINS", value_parser = parse_cors)]
 	pub rpc_cors: Option<Cors>,
 
-	/// Specify Prometheus exporter TCP Port.
-	#[arg(long, value_name = "PORT")]
-	pub prometheus_port: Option<u16>,
-
-	/// Do not expose a Prometheus exporter endpoint.
-	///
-	/// Prometheus metric endpoint is enabled by default.
-	#[arg(long)]
-	pub no_prometheus: bool,
-
 	/// The human-readable name for this node.
 	///
-	/// The node name will be reported to the telemetry server, if enabled.
+	/// It's used as network node name.
 	#[arg(long, value_name = "NAME")]
 	pub name: Option<String>,
 
-	/// Disable connecting to the Substrate telemetry server.
-	///
-	/// Telemetry is on by default on global chains.
-	#[arg(long)]
-	pub no_telemetry: bool,
+	#[allow(missing_docs)]
+	#[clap(flatten)]
+	pub telemetry_params: TelemetryParams,
 
-	/// The URL of the telemetry server to connect to.
-	///
-	/// This flag can be passed multiple times as a means to specify multiple
-	/// telemetry endpoints. Verbosity levels range from 0-9, with 0 denoting
-	/// the least verbosity.
-	/// Expected format is 'URL VERBOSITY', e.g. `--telemetry-url 'wss://foo/bar 0'`.
-	#[arg(long = "telemetry-url", value_name = "URL VERBOSITY", value_parser = parse_telemetry_endpoints)]
-	pub telemetry_endpoints: Vec<(String, u8)>,
+	#[allow(missing_docs)]
+	#[clap(flatten)]
+	pub prometheus_params: PrometheusParams,
+
+	#[allow(missing_docs)]
+	#[clap(flatten)]
+	pub runtime_params: RuntimeParams,
 
 	#[allow(missing_docs)]
 	#[clap(flatten)]
@@ -202,6 +183,10 @@ pub struct RunCmd {
 	#[clap(flatten)]
 	pub pool_config: TransactionPoolParams,
 
+	#[allow(missing_docs)]
+	#[clap(flatten)]
+	pub keystore_params: KeystoreParams,
+
 	/// Shortcut for `--name Alice --validator` with session keys for `Alice` added to keystore.
 	#[arg(long, conflicts_with_all = &["bob", "charlie", "dave", "eve", "ferdie", "one", "two"])]
 	pub alice: bool,
@@ -239,20 +224,6 @@ pub struct RunCmd {
 	#[arg(long)]
 	pub force_authoring: bool,
 
-	#[allow(missing_docs)]
-	#[clap(flatten)]
-	pub keystore_params: KeystoreParams,
-
-	/// The size of the instances cache for each runtime.
-	///
-	/// The default value is 8 and the values higher than 256 are ignored.
-	#[arg(long)]
-	pub max_runtime_instances: Option<usize>,
-
-	/// Maximum number of different runtimes that can be cached.
-	#[arg(long, default_value_t = 2)]
-	pub runtime_cache_size: u8,
-
 	/// Run a temporary node.
 	///
 	/// A temporary directory will be created to store the configuration and will be deleted
@@ -345,11 +316,12 @@ impl CliConfiguration for RunCmd {
 		&self,
 		chain_spec: &Box<dyn ChainSpec>,
 	) -> Result<Option<TelemetryEndpoints>> {
-		Ok(if self.no_telemetry {
+		let params = &self.telemetry_params;
+		Ok(if params.no_telemetry {
 			None
-		} else if !self.telemetry_endpoints.is_empty() {
+		} else if !params.telemetry_endpoints.is_empty() {
 			Some(
-				TelemetryEndpoints::new(self.telemetry_endpoints.clone())
+				TelemetryEndpoints::new(params.telemetry_endpoints.clone())
 					.map_err(|e| e.to_string())?,
 			)
 		} else {
@@ -361,7 +333,7 @@ impl CliConfiguration for RunCmd {
 		let keyring = self.get_keyring();
 		let is_authority = self.validator || is_dev || keyring.is_some();
 
-		Ok(if is_authority { sc_service::Role::Authority } else { sc_service::Role::Full })
+		Ok(if is_authority { Role::Authority } else { Role::Full })
 	}
 
 	fn force_authoring(&self) -> Result<bool> {
@@ -374,20 +346,9 @@ impl CliConfiguration for RunCmd {
 		default_listen_port: u16,
 		chain_spec: &Box<dyn ChainSpec>,
 	) -> Result<Option<PrometheusConfig>> {
-		Ok(if self.no_prometheus {
-			None
-		} else {
-			let interface =
-				if self.prometheus_external { Ipv4Addr::UNSPECIFIED } else { Ipv4Addr::LOCALHOST };
-
-			Some(PrometheusConfig::new_with_default_registry(
-				SocketAddr::new(
-					interface.into(),
-					self.prometheus_port.unwrap_or(default_listen_port),
-				),
-				chain_spec.id().into(),
-			))
-		})
+		Ok(self
+			.prometheus_params
+			.prometheus_config(default_listen_port, chain_spec.id().to_string()))
 	}
 
 	fn disable_grandpa(&self) -> Result<bool> {
@@ -474,11 +435,11 @@ impl CliConfiguration for RunCmd {
 	}
 
 	fn max_runtime_instances(&self) -> Result<Option<usize>> {
-		Ok(self.max_runtime_instances.map(|x| x.min(256)))
+		Ok(Some(self.runtime_params.max_runtime_instances))
 	}
 
 	fn runtime_cache_size(&self) -> Result<u8> {
-		Ok(self.runtime_cache_size)
+		Ok(self.runtime_params.runtime_cache_size)
 	}
 
 	fn base_path(&self) -> Result<Option<BasePath>> {
@@ -546,36 +507,6 @@ fn rpc_interface(
 	}
 }
 
-#[derive(Debug)]
-enum TelemetryParsingError {
-	MissingVerbosity,
-	VerbosityParsingError(std::num::ParseIntError),
-}
-
-impl std::error::Error for TelemetryParsingError {}
-
-impl std::fmt::Display for TelemetryParsingError {
-	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-		match self {
-			TelemetryParsingError::MissingVerbosity => write!(f, "Verbosity level missing"),
-			TelemetryParsingError::VerbosityParsingError(e) => write!(f, "{}", e),
-		}
-	}
-}
-
-fn parse_telemetry_endpoints(s: &str) -> std::result::Result<(String, u8), TelemetryParsingError> {
-	let pos = s.find(' ');
-	match pos {
-		None => Err(TelemetryParsingError::MissingVerbosity),
-		Some(pos_) => {
-			let url = s[..pos_].to_string();
-			let verbosity =
-				s[pos_ + 1..].parse().map_err(TelemetryParsingError::VerbosityParsingError)?;
-			Ok((url, verbosity))
-		},
-	}
-}
-
 /// CORS setting
 ///
 /// The type is introduced to overcome `Option<Option<T>>` handling of `clap`.
diff --git a/substrate/client/cli/src/params/keystore_params.rs b/substrate/client/cli/src/params/keystore_params.rs
index 8933110c400b7c64570a00bfbde841f8b690ac13..a2fdd6b2218c4b2dcadb03a6ca179d00a59868e2 100644
--- a/substrate/client/cli/src/params/keystore_params.rs
+++ b/substrate/client/cli/src/params/keystore_params.rs
@@ -61,7 +61,7 @@ pub struct KeystoreParams {
 	pub password_filename: Option<PathBuf>,
 }
 
-/// Parse a sercret string, returning a displayable error.
+/// Parse a secret string, returning a displayable error.
 pub fn secret_string_from_str(s: &str) -> std::result::Result<SecretString, String> {
 	std::str::FromStr::from_str(s).map_err(|_| "Could not get SecretString".to_string())
 }
diff --git a/substrate/client/cli/src/params/message_params.rs b/substrate/client/cli/src/params/message_params.rs
index a935bbb25bddd82f6056b3fde210b8412d438899..3fcb6f2c6e8cc918236df7e812786ec9da93354d 100644
--- a/substrate/client/cli/src/params/message_params.rs
+++ b/substrate/client/cli/src/params/message_params.rs
@@ -20,14 +20,13 @@
 
 use crate::error::Error;
 use array_bytes::{hex2bytes, hex_bytes2hex_str};
-use clap::Parser;
+use clap::Args;
 use std::io::BufRead;
 
 /// Params to configure how a message should be passed into a command.
-#[derive(Parser, Debug, Clone)]
+#[derive(Debug, Clone, Args)]
 pub struct MessageParams {
 	/// Message to process. Will be read from STDIN otherwise.
-	///
 	/// The message is assumed to be raw bytes per default. Use `--hex` for hex input. Can
 	/// optionally be prefixed with `0x` in the hex case.
 	#[arg(long)]
diff --git a/substrate/client/cli/src/params/mod.rs b/substrate/client/cli/src/params/mod.rs
index f9c840d2d486548add3004b7a34fc1ad28a54eda..247ffc0e04ba5cc69bef3fae55ee4d821d408046 100644
--- a/substrate/client/cli/src/params/mod.rs
+++ b/substrate/client/cli/src/params/mod.rs
@@ -22,8 +22,11 @@ mod message_params;
 mod network_params;
 mod node_key_params;
 mod offchain_worker_params;
+mod prometheus_params;
 mod pruning_params;
+mod runtime_params;
 mod shared_params;
+mod telemetry_params;
 mod transaction_pool_params;
 
 use crate::arg_enums::{CryptoScheme, OutputType};
@@ -37,8 +40,8 @@ use std::{fmt::Debug, str::FromStr};
 
 pub use crate::params::{
 	database_params::*, import_params::*, keystore_params::*, message_params::*, network_params::*,
-	node_key_params::*, offchain_worker_params::*, pruning_params::*, shared_params::*,
-	transaction_pool_params::*,
+	node_key_params::*, offchain_worker_params::*, prometheus_params::*, pruning_params::*,
+	runtime_params::*, shared_params::*, telemetry_params::*, transaction_pool_params::*,
 };
 
 /// Parse Ss58AddressFormat
diff --git a/substrate/client/cli/src/params/prometheus_params.rs b/substrate/client/cli/src/params/prometheus_params.rs
new file mode 100644
index 0000000000000000000000000000000000000000..69199ad5b260329bb49f4b8e8f0781daa17e15fb
--- /dev/null
+++ b/substrate/client/cli/src/params/prometheus_params.rs
@@ -0,0 +1,63 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+use clap::Args;
+use sc_service::config::PrometheusConfig;
+use std::net::{Ipv4Addr, SocketAddr};
+
+/// Parameters used to config prometheus.
+#[derive(Debug, Clone, Args)]
+pub struct PrometheusParams {
+	/// Specify Prometheus exporter TCP Port.
+	#[arg(long, value_name = "PORT")]
+	pub prometheus_port: Option<u16>,
+	/// Expose Prometheus exporter on all interfaces.
+	///
+	/// Default is local.
+	#[arg(long)]
+	pub prometheus_external: bool,
+	/// Do not expose a Prometheus exporter endpoint.
+	///
+	/// Prometheus metric endpoint is enabled by default.
+	#[arg(long)]
+	pub no_prometheus: bool,
+}
+
+impl PrometheusParams {
+	/// Creates [`PrometheusConfig`].
+	pub fn prometheus_config(
+		&self,
+		default_listen_port: u16,
+		chain_id: String,
+	) -> Option<PrometheusConfig> {
+		if self.no_prometheus {
+			None
+		} else {
+			let interface =
+				if self.prometheus_external { Ipv4Addr::UNSPECIFIED } else { Ipv4Addr::LOCALHOST };
+
+			Some(PrometheusConfig::new_with_default_registry(
+				SocketAddr::new(
+					interface.into(),
+					self.prometheus_port.unwrap_or(default_listen_port),
+				),
+				chain_id,
+			))
+		}
+	}
+}
diff --git a/substrate/client/cli/src/params/pruning_params.rs b/substrate/client/cli/src/params/pruning_params.rs
index 59eeb13cd037902074aeec213fc196de0dea1522..757da2dd9cbb54b18989f5727acbac48207fbfe1 100644
--- a/substrate/client/cli/src/params/pruning_params.rs
+++ b/substrate/client/cli/src/params/pruning_params.rs
@@ -21,7 +21,7 @@ use clap::Args;
 use sc_service::{BlocksPruning, PruningMode};
 
 /// Parameters to define the pruning mode
-#[derive(Debug, Clone, PartialEq, Args)]
+#[derive(Debug, Clone, Args)]
 pub struct PruningParams {
 	/// Specify the state pruning mode.
 	///
diff --git a/substrate/client/cli/src/params/runtime_params.rs b/substrate/client/cli/src/params/runtime_params.rs
new file mode 100644
index 0000000000000000000000000000000000000000..79035fc7d4c5d7cf082969a4d709b8181bb176eb
--- /dev/null
+++ b/substrate/client/cli/src/params/runtime_params.rs
@@ -0,0 +1,43 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+use clap::Args;
+use std::str::FromStr;
+
+/// Parameters used to config runtime.
+#[derive(Debug, Clone, Args)]
+pub struct RuntimeParams {
+	/// The size of the instances cache for each runtime. The values higher than 256 are illegal.
+	#[arg(long, default_value_t = 8, value_parser = parse_max_runtime_instances)]
+	pub max_runtime_instances: usize,
+
+	/// Maximum number of different runtimes that can be cached.
+	#[arg(long, default_value_t = 2)]
+	pub runtime_cache_size: u8,
+}
+
+fn parse_max_runtime_instances(s: &str) -> Result<usize, String> {
+	let max_runtime_instances = usize::from_str(s)
+		.map_err(|_err| format!("Illegal `--max-runtime-instances` value: {s}"))?;
+
+	if max_runtime_instances > 256 {
+		Err(format!("Illegal `--max-runtime-instances` value: {max_runtime_instances} is more than the allowed maximum of `256` "))
+	} else {
+		Ok(max_runtime_instances)
+	}
+}
diff --git a/substrate/client/cli/src/params/shared_params.rs b/substrate/client/cli/src/params/shared_params.rs
index 46f5390039d46fe1780e391e9f30bf5b4b2ae018..913a6c436185cceb9cc0f0dc874d2a91473d1e1f 100644
--- a/substrate/client/cli/src/params/shared_params.rs
+++ b/substrate/client/cli/src/params/shared_params.rs
@@ -22,7 +22,7 @@ use sc_service::config::BasePath;
 use std::path::PathBuf;
 
 /// Shared parameters used by all `CoreParams`.
-#[derive(Debug, Clone, PartialEq, Args)]
+#[derive(Debug, Clone, Args)]
 pub struct SharedParams {
 	/// Specify the chain specification.
 	///
diff --git a/substrate/client/cli/src/params/telemetry_params.rs b/substrate/client/cli/src/params/telemetry_params.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ca096419869afc1ce7b9036dc659cefdd2d3a1e4
--- /dev/null
+++ b/substrate/client/cli/src/params/telemetry_params.rs
@@ -0,0 +1,68 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+use clap::Args;
+
+/// Parameters used to config telemetry.
+#[derive(Debug, Clone, Args)]
+pub struct TelemetryParams {
+	/// Disable connecting to the Substrate telemetry server.
+	///
+	/// Telemetry is on by default on global chains.
+	#[arg(long)]
+	pub no_telemetry: bool,
+
+	/// The URL of the telemetry server to connect to.
+	///
+	/// This flag can be passed multiple times as a means to specify multiple
+	/// telemetry endpoints. Verbosity levels range from 0-9, with 0 denoting
+	/// the least verbosity.
+	/// Expected format is 'URL VERBOSITY', e.g. `--telemetry-url 'wss://foo/bar 0'`.
+	#[arg(long = "telemetry-url", value_name = "URL VERBOSITY", value_parser = parse_telemetry_endpoints)]
+	pub telemetry_endpoints: Vec<(String, u8)>,
+}
+
+#[derive(Debug)]
+enum TelemetryParsingError {
+	MissingVerbosity,
+	VerbosityParsingError(std::num::ParseIntError),
+}
+
+impl std::error::Error for TelemetryParsingError {}
+
+impl std::fmt::Display for TelemetryParsingError {
+	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+		match self {
+			TelemetryParsingError::MissingVerbosity => write!(f, "Verbosity level missing"),
+			TelemetryParsingError::VerbosityParsingError(e) => write!(f, "{}", e),
+		}
+	}
+}
+
+fn parse_telemetry_endpoints(s: &str) -> Result<(String, u8), TelemetryParsingError> {
+	let pos = s.find(' ');
+	match pos {
+		None => Err(TelemetryParsingError::MissingVerbosity),
+		Some(pos_) => {
+			let url = s[..pos_].to_string();
+			let verbosity =
+				s[pos_ + 1..].parse().map_err(TelemetryParsingError::VerbosityParsingError)?;
+			Ok((url, verbosity))
+		},
+	}
+}