diff --git a/r11k/puppetfile.py b/r11k/puppetfile.py
index 4fd7ca67e7ce68fbf700df77057a620f0284a2d1..1cd2c05a6565c1a56cafe4b4ec8ead6aa35cd3b6 100644
--- a/r11k/puppetfile.py
+++ b/r11k/puppetfile.py
@@ -194,15 +194,32 @@ def parse_puppetfile(data: dict[str, Any],
     """Parse data from puppetfile dictionary."""
     pf = PuppetFile()
 
+    if subpath := data.get('include'):
+        if not path:
+            raise ValueError('include only possible when we have a source file')
+        inc_path = os.path.join(os.path.dirname(path), subpath)
+        parent = load_puppetfile(inc_path)
+        pf.include(parent)
+
     if config:
         pf.config = config
 
+    removed: list[str] = []
     for module in data['modules']:
         if config:
             module['config'] = config
         m = parse_module_dict(module)
-        m.explicit = True
-        pf.modules[m.name] = m
+        if m == 'remove':
+            removed.append(module['name'])
+        else:
+            m.explicit = True
+            pf.modules[m.name] = m
+
+    for r in removed:
+        # This WILL fail if we try to remove a non-added module.
+        # Possibly catch this and instead throw a better error message
+        # that this is by design.
+        del pf.modules[r]
 
     if env := data.get('environment'):
         pf.environment_name = env
@@ -215,13 +232,6 @@ def parse_puppetfile(data: dict[str, Any],
     if hiera := data.get('hiera'):
         pf.hiera = hiera
 
-    if subpath := data.get('include'):
-        if not path:
-            raise ValueError('include only possible when we have a source file')
-        path = os.path.join(os.path.dirname(path), subpath)
-        parent = load_puppetfile(path)
-        pf.include(parent)
-
     return pf
 
 
diff --git a/r11k/puppetmodule/__init__.py b/r11k/puppetmodule/__init__.py
index 7951f2c5d0036e0de2b35851c7e387de96b43031..23056b9968b33fe6991eba7175db0884189dd500 100644
--- a/r11k/puppetmodule/__init__.py
+++ b/r11k/puppetmodule/__init__.py
@@ -16,16 +16,21 @@ The implementations are in
 from .base import PuppetModule
 from .git import GitPuppetModule
 from .forge import ForgePuppetModule
+from typing import (
+    Literal,
+)
 
 
-def parse_module_dict(d: dict) -> PuppetModule:
+def parse_module_dict(d: dict) -> PuppetModule | Literal['remove']:
     """
     Parse dict describing module into module object.
 
     Currently, it becomes a `GitPuppetModule` if the `git` key is
     present, and a `ForgePuppetModule` otherwise.
     """
-    if 'git' in d:
+    if 'remove' in d and d['remove']:
+        return 'remove'
+    elif 'git' in d:
         return GitPuppetModule(**d)
     else:
         return ForgePuppetModule(**d)