diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 84e020cd3d..0cede11d67 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -3565,7 +3565,7 @@ class DevtoolIdeSdkTests(DevtoolBase):
         self._verify_nfs_launch_json(tempdir, nfs_rootfs)
 
     def _test_devtool_ide_sdk_code_and_none_qemu(self, nfs=False, slirp=False):
-        """Verify devtool ide-sdk --ide=code,none for cmake, meson and the target toolchain.
+        """Verify devtool ide-sdk --ide=code --ide=none for cmake, meson and the target toolchain.
 
         Generating the VS Code (ide=code) and generic (ide=none) IDE
         configurations from a SINGLE devtool ide-sdk invocation and check
@@ -3607,7 +3607,7 @@ class DevtoolIdeSdkTests(DevtoolBase):
             self._meson_recipe_name, "meson.build", testimage)
         package_opts = self._ide_sdk_package_opts()
         nfs_opts = ' --nfs=%s' % nfs_export if nfs else ''
-        runCmd('devtool ide-sdk %s -c --ide=code,none %s%s' % (testimage, package_opts, nfs_opts),
+        runCmd('devtool ide-sdk %s -c --ide=code --ide=none %s%s' % (testimage, package_opts, nfs_opts),
                output_log=self._cmd_logger)
 
         if slirp:
@@ -3649,7 +3649,7 @@ class DevtoolIdeSdkTests(DevtoolBase):
             # not known at the time of the initial ide-sdk invocation.
             # --skip-bitbake also skips the NFS rootfs (re-)extraction, which
             # would otherwise wipe the directory the target has mounted.
-            bitbake_sdk_cmd = 'devtool ide-sdk %s %s --skip-bitbake --ide=code,none %s%s' % (
+            bitbake_sdk_cmd = 'devtool ide-sdk %s %s --skip-bitbake --ide=code --ide=none %s%s' % (
                 testimage, target_options, package_opts, nfs_opts)
             runCmd(bitbake_sdk_cmd, output_log=self._cmd_logger)
 
@@ -4231,7 +4231,7 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests):
 
     @OETestTag("runqemu")
     def test_devtool_ide_sdk_code_and_none_qemu(self):
-        """Verify devtool ide-sdk --ide=code,none for cmake-example/meson-example with GCC and GDB."""
+        """Verify devtool ide-sdk --ide=code --ide=none for cmake-example/meson-example with GCC and GDB."""
         self._test_devtool_ide_sdk_code_and_none_qemu()
 
     @OETestTag("runqemu")
@@ -5051,7 +5051,7 @@ class DevtoolIdeSdkClangTests(DevtoolIdeSdkTests):
 
     @OETestTag("runqemu")
     def test_devtool_ide_sdk_code_and_none_qemu(self):
-        """Verify devtool ide-sdk --ide=code,none for cmake/meson-example-clang with Clang and LLDB.
+        """Verify devtool ide-sdk --ide=code --ide=none for cmake/meson-example-clang with Clang and LLDB.
 
         See DevtoolIdeSdkTests._test_devtool_ide_sdk_code_and_none_qemu for
         the shared workflow. Clang-specific here: the generated configs
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index 8f2e768a62..20b03b2d40 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -1714,7 +1714,10 @@ def ide_setup(args, config, basepath, workspace):
         config, args.recipenames)
     orig_recipe_bbappend_contents = RecipeModified.strip_bbappend_sections(
         config, args.recipenames)
-    ides = [ide_plugins[name]() for name in args.ide]
+    ide_names = args.ide or [list(ide_plugins.keys())[0]]
+    if 'all' in ide_names:
+        ide_names = list(ide_plugins.keys())
+    ides = [ide_plugins[name]() for name in ide_names]
     tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
     try:
         # define mode depending on recipes which need to be processed
@@ -2014,21 +2017,13 @@ def register_commands(subparsers, context):
         '  To use this tool-chain the environment-* file found in the deploy..image folder needs to be sourced into a shell.\n'
         '  In case of VSCode and cmake the tool-chain is also exposed as a cmake-kit')
     default_ide = list(ide_plugins.keys())[0]
-
-    def ide_list(value):
-        """argparse type: comma separated list of IDE plugin names"""
-        names = value.split(',')
-        for name in names:
-            if name not in ide_plugins:
-                raise ValueError(
-                    "invalid choice: %r (choose from %s)" % (
-                        name, ', '.join(sorted(ide_plugins.keys()))))
-        return names
+    ide_choices = list(ide_plugins.keys()) + ['all']
     parser_ide_sdk.add_argument(
-        '-i', '--ide', type=ide_list, default=[default_ide],
-        metavar='{%s}' % ','.join(ide_plugins.keys()),
-        help='Comma separated list of IDEs to setup the configuration for '
-        '(choices: %s, default: %s)' % (', '.join(ide_plugins.keys()), default_ide))
+        '-i', '--ide', action='append', choices=ide_choices,
+        metavar='{%s}' % ','.join(ide_choices),
+        help='IDE to setup the configuration for. May be specified multiple times '
+        'to set up more than one IDE. "all" sets up every supported IDE '
+        '(choices: %s, default: %s)' % (', '.join(ide_choices), default_ide))
     parser_ide_sdk.add_argument(
         '-t', '--target', default='root@192.168.7.2',
         help='Live target machine running an ssh server: user@hostname.')
