diff --git a/doc/source/custom-ansible-playbooks.rst b/doc/source/custom-ansible-playbooks.rst
index 0c61793679a05ff5d0298210783fbfdb59a497ef..890dfdf8a1a585ab90c5924a784c17b9c19fa585 100644
--- a/doc/source/custom-ansible-playbooks.rst
+++ b/doc/source/custom-ansible-playbooks.rst
@@ -213,6 +213,24 @@ you could do the following::
 
 The sequence number for the ``foo.yml`` playbook is ``10``.
 
+Hook execution can be disabled with ``--skip-hooks``. ``--skip-hooks all`` will halt hook execution altogether.
+``--skip-hooks <pattern>`` will skip playbooks matching the ``<pattern>``.
+
+For example, if the following playbooks exist:
+
+- ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/pre.d/example1.yml``
+- ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/pre.d/example2.yml``
+- ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/post.d/example1.yml``
+
+And the following command is used::
+
+    (kayobe) $ kayobe control host bootstrap --skip-hooks example1
+
+Only ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/pre.d/example2.yml`` will be executed.
+
+This example assumes that the term ``example1`` does not appear in
+``$KAYOBE_CONFIG_PATH``. If it did, all hooks would be skipped.
+
 Failure handling
 ----------------
 
diff --git a/kayobe/ansible.py b/kayobe/ansible.py
index 9d47a9243b76cd48dcf206c4be0b34b52e53fe55..dd5bc66dfcbe8a12ced4731650b8853c44e5c0b2 100644
--- a/kayobe/ansible.py
+++ b/kayobe/ansible.py
@@ -77,6 +77,9 @@ def add_args(parser):
                         action="store_true",
                         help="only print names of tasks, don't run them, "
                              "note this has no affect on kolla-ansible.")
+    parser.add_argument("-sh", "--skip-hooks", action="store", default=None,
+                        help="disables hooks. Specify a pattern to skip"
+                             "specific playbooks. \"all\" skips all playbooks")
 
 
 def _get_kayobe_environment_path(parsed_args):
diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py
index 315c787bf4e29852c63435d58686e721f1e7d47a..11fc164f02d1f661694f9558b3a604cb1e8bb2ed 100644
--- a/kayobe/cli/commands.py
+++ b/kayobe/cli/commands.py
@@ -15,6 +15,7 @@
 import glob
 import json
 import os
+import re
 import sys
 
 from cliff.command import Command
@@ -190,18 +191,27 @@ class HookDispatcher(CommandHook):
         self.logger.debug("Discovered the following hooks: %s" % hooks)
         return hooks
 
-    def hooks(self, config_path, target):
-        hooks = self._find_hooks(config_path, target)
+    def hooks(self, config_path, target, filter):
+        hooks_out = []
+        if filter == "all":
+            self.logger.debug("Skipping all hooks")
+            return hooks_out
+        hooks_in = self._find_hooks(config_path, target)
         # Hooks can be prefixed with a sequence number to adjust running order,
         # e.g 10-my-custom-playbook.yml. Sort by sequence number.
-        hooks = sorted(hooks, key=_split_hook_sequence_number)
-        # Resolve symlinks so that we can reference roles.
-        hooks = [os.path.realpath(hook) for hook in hooks]
-        return hooks
+        hooks_in = sorted(hooks_in, key=_split_hook_sequence_number)
+        for hook in hooks_in:
+            # Resolve symlinks so that we can reference roles.
+            hook = os.path.realpath(hook)
+            if filter and re.search(filter, hook):
+                self.logger.debug("Skipping hook: %s", hook)
+            else:
+                hooks_out.append(hook)
+        return hooks_out
 
     def run_hooks(self, parsed_args, target):
         config_path = parsed_args.config_path
-        hooks = self.hooks(config_path, target)
+        hooks = self.hooks(config_path, target, parsed_args.skip_hooks)
         if hooks:
             self.logger.debug("Running hooks: %s" % hooks)
             self.command.run_kayobe_playbooks(parsed_args, hooks)
diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py
index c86671815b11973d2a3bf058e6d78db701c1a2e3..6d8952deb4d12797fec9b59c3f369997e6a8e18f 100644
--- a/kayobe/tests/unit/cli/test_commands.py
+++ b/kayobe/tests/unit/cli/test_commands.py
@@ -2506,5 +2506,47 @@ class TestHookDispatcher(unittest.TestCase):
             "z-test-alphabetical.yml",
         ]
         mock_path.realpath.side_effect = lambda x: x
-        actual = dispatcher.hooks("config/path", "pre")
+        actual = dispatcher.hooks("config/path", "pre", None)
+        self.assertListEqual(actual, expected_result)
+
+    @mock.patch('kayobe.cli.commands.os.path')
+    def test_hook_filter_all(self, mock_path):
+        mock_command = mock.MagicMock()
+        dispatcher = commands.HookDispatcher(command=mock_command)
+        dispatcher._find_hooks = mock.MagicMock()
+        dispatcher._find_hooks.return_value = [
+            "5-hook.yml",
+            "5-multiple-dashes-in-name.yml",
+            "10-before-hook.yml",
+            "10-hook.yml",
+            "no-prefix.yml",
+            "z-test-alphabetical.yml",
+        ]
+        mock_path.realpath.side_effect = lambda x: x
+        actual = dispatcher.hooks("config/path", "pre", "all")
+        self.assertListEqual(actual, [])
+
+    @mock.patch('kayobe.cli.commands.os.path')
+    def test_hook_filter_one(self, mock_path):
+        mock_command = mock.MagicMock()
+        dispatcher = commands.HookDispatcher(command=mock_command)
+        dispatcher._find_hooks = mock.MagicMock()
+        dispatcher._find_hooks.return_value = [
+            "5-hook.yml",
+            "5-multiple-dashes-in-name.yml",
+            "10-before-hook.yml",
+            "10-hook.yml",
+            "no-prefix.yml",
+            "z-test-alphabetical.yml",
+        ]
+        expected_result = [
+            "5-hook.yml",
+            "10-before-hook.yml",
+            "10-hook.yml",
+            "no-prefix.yml",
+            "z-test-alphabetical.yml",
+        ]
+        mock_path.realpath.side_effect = lambda x: x
+        actual = dispatcher.hooks("config/path", "pre",
+                                  "5-multiple-dashes-in-name.yml")
         self.assertListEqual(actual, expected_result)
diff --git a/releasenotes/notes/add-option-to-skip-hooks-719ba214a6d4b773.yaml b/releasenotes/notes/add-option-to-skip-hooks-719ba214a6d4b773.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e80cea09241c38744b052130321ec3b1e9fa0ad4
--- /dev/null
+++ b/releasenotes/notes/add-option-to-skip-hooks-719ba214a6d4b773.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Adds the --skip-hooks argument to ignore hooks for the execution of a
+    command. See `story 2009241
+    <https://storyboard.openstack.org/#!/story/2009241>`_ for details.
\ No newline at end of file