diff --git a/xtask/src/install.rs b/xtask/src/install.rs
index 789e9f27bfa..78a8af7974a 100644
--- a/xtask/src/install.rs
+++ b/xtask/src/install.rs
@@ -13,8 +13,43 @@ pub struct InstallCmd {
     pub server: Option<ServerOpt>,
 }
 
+#[derive(Clone, Copy)]
 pub enum ClientOpt {
     VsCode,
+    VsCodeInsiders,
+    VsCodium,
+    VsCodeOss,
+    Any,
+}
+
+impl ClientOpt {
+    pub const fn as_cmds(&self) -> &'static [&'static str] {
+        match self {
+            ClientOpt::VsCode => &["code"],
+            ClientOpt::VsCodeInsiders => &["code-insiders"],
+            ClientOpt::VsCodium => &["codium"],
+            ClientOpt::VsCodeOss => &["code-oss"],
+            ClientOpt::Any => &["code", "code-insiders", "codium", "code-oss"],
+        }
+    }
+}
+
+impl Default for ClientOpt {
+    fn default() -> Self {
+        ClientOpt::Any
+    }
+}
+
+impl std::str::FromStr for ClientOpt {
+    type Err = anyhow::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        [ClientOpt::VsCode, ClientOpt::VsCodeInsiders, ClientOpt::VsCodium, ClientOpt::VsCodeOss]
+            .iter()
+            .copied()
+            .find(|c| [s] == c.as_cmds())
+            .ok_or_else(|| anyhow::format_err!("no such client"))
+    }
 }
 
 pub struct ServerOpt {
@@ -74,17 +109,13 @@ fn fix_path_for_mac() -> Result<()> {
     Ok(())
 }
 
-fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
-    let _dir = pushd("./editors/code")?;
+fn install_client(client_opt: ClientOpt) -> Result<()> {
+    let _dir = pushd("./editors/code");
 
     let find_code = |f: fn(&str) -> bool| -> Result<&'static str> {
-        ["code", "code-insiders", "codium", "code-oss"]
-            .iter()
-            .copied()
-            .find(|bin| f(bin))
-            .ok_or_else(|| {
-                format_err!("Can't execute `code --version`. Perhaps it is not in $PATH?")
-            })
+        client_opt.as_cmds().iter().copied().find(|bin| f(bin)).ok_or_else(|| {
+            format_err!("Can't execute `code --version`. Perhaps it is not in $PATH?")
+        })
     };
 
     let installed_extensions = if cfg!(unix) {
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 97e5dcd4e5b..536a670477f 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -16,7 +16,7 @@ use xshell::pushd;
 use xtask::{
     codegen::{self, Mode},
     dist::DistCmd,
-    install::{ClientOpt, InstallCmd, Malloc, ServerOpt},
+    install::{InstallCmd, Malloc, ServerOpt},
     metrics::MetricsCmd,
     pre_cache::PreCacheCmd,
     pre_commit, project_root,
@@ -46,19 +46,20 @@ USAGE:
     cargo xtask install [FLAGS]
 
 FLAGS:
-        --client-code    Install only VS Code plugin
-        --server         Install only the language server
-        --mimalloc       Use mimalloc for server
-    -h, --help           Prints help information
+        --client[=CLIENT] Install only VS Code plugin.
+                          CLIENT is one of 'code', 'code-insiders', 'codium', or 'code-oss'
+        --server          Install only the language server
+        --mimalloc        Use mimalloc for server
+    -h, --help            Prints help information
         "
                 );
                 return Ok(());
             }
             let server = args.contains("--server");
-            let client_code = args.contains("--client-code");
+            let client_code = args.contains("--client");
             if server && client_code {
                 eprintln!(
-                    "error: The argument `--server` cannot be used with `--client-code`\n\n\
+                    "error: The argument `--server` cannot be used with `--client`\n\n\
                      For more information try --help"
                 );
                 return Ok(());
@@ -67,10 +68,12 @@ FLAGS:
             let malloc =
                 if args.contains("--mimalloc") { Malloc::Mimalloc } else { Malloc::System };
 
+            let client_opt = args.opt_value_from_str("--client")?;
+
             args.finish()?;
 
             InstallCmd {
-                client: if server { None } else { Some(ClientOpt::VsCode) },
+                client: if server { None } else { Some(client_opt.unwrap_or_default()) },
                 server: if client_code { None } else { Some(ServerOpt { malloc }) },
             }
             .run()