diff --git a/lib/python/qmk/cli/compile.py b/lib/python/qmk/cli/compile.py
index f43e5f32de..3d632e74a9 100755
--- a/lib/python/qmk/cli/compile.py
+++ b/lib/python/qmk/cli/compile.py
@@ -9,7 +9,7 @@ from milc import cli
 import qmk.path
 from qmk.decorators import automagic_keyboard, automagic_keymap
 from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json, build_environment
-from qmk.keyboard import keyboard_completer, keyboard_folder
+from qmk.keyboard import keyboard_completer, keyboard_folder_or_all, is_all_keyboards
 from qmk.keymap import keymap_completer, locate_keymap
 
 
@@ -24,7 +24,7 @@ def _is_keymap_target(keyboard, keymap):
 
 
 @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='The configurator export to compile')
-@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.')
+@cli.argument('-kb', '--keyboard', type=keyboard_folder_or_all, completer=keyboard_completer, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.')
 @cli.argument('-km', '--keymap', completer=keymap_completer, help='The keymap to build a firmware for. Ignored when a configurator export is supplied.')
 @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.")
 @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.")
@@ -40,6 +40,13 @@ def compile(cli):
 
     If a keyboard and keymap are provided this command will build a firmware based on that.
     """
+    if is_all_keyboards(cli.args.keyboard):
+        from .mass_compile import mass_compile
+        cli.args.builds = []
+        cli.args.filter = []
+        cli.args.no_temp = False
+        return mass_compile(cli)
+
     # Build the environment vars
     envs = build_environment(cli.args.env)
 
diff --git a/lib/python/qmk/cli/mass_compile.py b/lib/python/qmk/cli/mass_compile.py
index ddd946a32b..bac80e9747 100755
--- a/lib/python/qmk/cli/mass_compile.py
+++ b/lib/python/qmk/cli/mass_compile.py
@@ -17,6 +17,7 @@ from qmk.search import search_keymap_targets
 @cli.argument('-t', '--no-temp', arg_only=True, action='store_true', help="Remove temporary files during build.")
 @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs; 0 means unlimited.")
 @cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.")
+@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the commands to be run.")
 @cli.argument(
     '-f',
     '--filter',
@@ -47,47 +48,52 @@ def mass_compile(cli):
     if len(targets) == 0:
         return
 
-    builddir.mkdir(parents=True, exist_ok=True)
-    with open(makefile, "w") as f:
+    if cli.args.dry_run:
+        cli.log.info('Compilation targets:')
         for target in sorted(targets):
-            keyboard_name = target[0]
-            keymap_name = target[1]
-            keyboard_safe = keyboard_name.replace('/', '_')
-            build_log = f"{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
-            failed_log = f"{QMK_FIRMWARE}/.build/failed.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
-            # yapf: disable
-            f.write(
-                f"""\
-all: {keyboard_safe}_{keymap_name}_binary
-{keyboard_safe}_{keymap_name}_binary:
-	@rm -f "{build_log}" || true
-	@echo "Compiling QMK Firmware for target: '{keyboard_name}:{keymap_name}'..." >>"{build_log}"
-	+@$(MAKE) -C "{QMK_FIRMWARE}" -f "{QMK_FIRMWARE}/builddefs/build_keyboard.mk" KEYBOARD="{keyboard_name}" KEYMAP="{keymap_name}" COLOR=true SILENT=false {' '.join(cli.args.env)} \\
-		>>"{build_log}" 2>&1 \\
-		|| cp "{build_log}" "{failed_log}"
-	@{{ grep '\[ERRORS\]' "{build_log}" >/dev/null 2>&1 && printf "Build %-64s \e[1;31m[ERRORS]\e[0m\\n" "{keyboard_name}:{keymap_name}" ; }} \\
-		|| {{ grep '\[WARNINGS\]' "{build_log}" >/dev/null 2>&1 && printf "Build %-64s \e[1;33m[WARNINGS]\e[0m\\n" "{keyboard_name}:{keymap_name}" ; }} \\
-		|| printf "Build %-64s \e[1;32m[OK]\e[0m\\n" "{keyboard_name}:{keymap_name}"
-	@rm -f "{build_log}" || true
-"""# noqa
-            )
-            # yapf: enable
-
-            if cli.args.no_temp:
+            cli.log.info(f"{{fg_cyan}}qmk compile -kb {target[0]} -km {target[1]}{{fg_reset}}")
+    else:
+        builddir.mkdir(parents=True, exist_ok=True)
+        with open(makefile, "w") as f:
+            for target in sorted(targets):
+                keyboard_name = target[0]
+                keymap_name = target[1]
+                keyboard_safe = keyboard_name.replace('/', '_')
+                build_log = f"{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
+                failed_log = f"{QMK_FIRMWARE}/.build/failed.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
                 # yapf: disable
                 f.write(
                     f"""\
-	@rm -rf "{QMK_FIRMWARE}/.build/{keyboard_safe}_{keymap_name}.elf" 2>/dev/null || true
-	@rm -rf "{QMK_FIRMWARE}/.build/{keyboard_safe}_{keymap_name}.map" 2>/dev/null || true
-	@rm -rf "{QMK_FIRMWARE}/.build/obj_{keyboard_safe}_{keymap_name}" || true
-"""# noqa
+    all: {keyboard_safe}_{keymap_name}_binary
+    {keyboard_safe}_{keymap_name}_binary:
+        @rm -f "{build_log}" || true
+        @echo "Compiling QMK Firmware for target: '{keyboard_name}:{keymap_name}'..." >>"{build_log}"
+        +@$(MAKE) -C "{QMK_FIRMWARE}" -f "{QMK_FIRMWARE}/builddefs/build_keyboard.mk" KEYBOARD="{keyboard_name}" KEYMAP="{keymap_name}" COLOR=true SILENT=false {' '.join(cli.args.env)} \\
+            >>"{build_log}" 2>&1 \\
+            || cp "{build_log}" "{failed_log}"
+        @{{ grep '\[ERRORS\]' "{build_log}" >/dev/null 2>&1 && printf "Build %-64s \e[1;31m[ERRORS]\e[0m\\n" "{keyboard_name}:{keymap_name}" ; }} \\
+            || {{ grep '\[WARNINGS\]' "{build_log}" >/dev/null 2>&1 && printf "Build %-64s \e[1;33m[WARNINGS]\e[0m\\n" "{keyboard_name}:{keymap_name}" ; }} \\
+            || printf "Build %-64s \e[1;32m[OK]\e[0m\\n" "{keyboard_name}:{keymap_name}"
+        @rm -f "{build_log}" || true
+    """# noqa
                 )
                 # yapf: enable
-            f.write('\n')
 
-    cli.run([make_cmd, *get_make_parallel_args(cli.args.parallel), '-f', makefile.as_posix(), 'all'], capture_output=False, stdin=DEVNULL)
+                if cli.args.no_temp:
+                    # yapf: disable
+                    f.write(
+                        f"""\
+        @rm -rf "{QMK_FIRMWARE}/.build/{keyboard_safe}_{keymap_name}.elf" 2>/dev/null || true
+        @rm -rf "{QMK_FIRMWARE}/.build/{keyboard_safe}_{keymap_name}.map" 2>/dev/null || true
+        @rm -rf "{QMK_FIRMWARE}/.build/obj_{keyboard_safe}_{keymap_name}" || true
+    """# noqa
+                    )
+                    # yapf: enable
+                f.write('\n')
 
-    # Check for failures
-    failures = [f for f in builddir.glob(f'failed.log.{os.getpid()}.*')]
-    if len(failures) > 0:
-        return False
+        cli.run([make_cmd, *get_make_parallel_args(cli.args.parallel), '-f', makefile.as_posix(), 'all'], capture_output=False, stdin=DEVNULL)
+
+        # Check for failures
+        failures = [f for f in builddir.glob(f'failed.log.{os.getpid()}.*')]
+        if len(failures) > 0:
+            return False
diff --git a/lib/python/qmk/keyboard.py b/lib/python/qmk/keyboard.py
index 235b62640c..3e5cae4b22 100644
--- a/lib/python/qmk/keyboard.py
+++ b/lib/python/qmk/keyboard.py
@@ -30,9 +30,29 @@ BOX_DRAWING_CHARACTERS = {
     },
 }
 
+
+class AllKeyboards:
+    """Represents all keyboards.
+    """
+    def __str__(self):
+        return 'all'
+
+    def __repr__(self):
+        return 'all'
+
+    def __eq__(self, other):
+        return isinstance(other, AllKeyboards)
+
+
 base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep
 
 
+def is_all_keyboards(keyboard):
+    """Returns True if the keyboard is an AllKeyboards object.
+    """
+    return isinstance(keyboard, AllKeyboards)
+
+
 def find_keyboard_from_dir():
     """Returns a keyboard name based on the user's current directory.
     """
@@ -86,6 +106,18 @@ def keyboard_folder(keyboard):
     return keyboard
 
 
+def keyboard_folder_or_all(keyboard):
+    """Returns the actual keyboard folder.
+
+    This checks aliases and DEFAULT_FOLDER to resolve the actual path for a keyboard.
+    If the supplied argument is "all", it returns an AllKeyboards object.
+    """
+    if keyboard == 'all':
+        return AllKeyboards()
+
+    return keyboard_folder(keyboard)
+
+
 def _find_name(path):
     """Determine the keyboard name by stripping off the base_path and rules.mk.
     """