diff --git a/app/dts/bindings/input_processors/zmk,input-processor-out-of-band-behaviors.yaml b/app/dts/bindings/input_processors/zmk,input-processor-out-of-band-behaviors.yaml
new file mode 100644
index 00000000000..d3c0b3ce538
--- /dev/null
+++ b/app/dts/bindings/input_processors/zmk,input-processor-out-of-band-behaviors.yaml
@@ -0,0 +1,18 @@
+# Copyright (c) 2024, The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+description: Input Processor for invoking out of band behaviors on certain events
+
+compatible: "zmk,input-processor-out-of-band-behaviors"
+
+include: ip_zero_param.yaml
+
+properties:
+ type:
+ type: int
+ codes:
+ type: array
+ required: true
+ bindings:
+ type: phandle-array
+ required: true
diff --git a/app/dts/input/processors.dtsi b/app/dts/input/processors.dtsi
index d072c0fcfcf..4b517c032c0 100644
--- a/app/dts/input/processors.dtsi
+++ b/app/dts/input/processors.dtsi
@@ -7,4 +7,5 @@
#include
#include
#include
-#include
\ No newline at end of file
+#include
+#include
\ No newline at end of file
diff --git a/app/dts/input/processors/oobb.dtsi b/app/dts/input/processors/oobb.dtsi
new file mode 100644
index 00000000000..3047e7a0294
--- /dev/null
+++ b/app/dts/input/processors/oobb.dtsi
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2024 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include
+
+/ {
+ zip_out_of_band_button_behaviors: zip_out_of_band_button_behaviors {
+ compatible = "zmk,input-processor-out-of-band-behaviors";
+ #input-processor-cells = <0>;
+ codes = ;
+ bindings = <&none &none &none>;
+ };
+};
\ No newline at end of file
diff --git a/app/src/pointing/CMakeLists.txt b/app/src/pointing/CMakeLists.txt
index ad74c1ea786..8db1bf509d4 100644
--- a/app/src/pointing/CMakeLists.txt
+++ b/app/src/pointing/CMakeLists.txt
@@ -6,5 +6,6 @@ target_sources_ifdef(CONFIG_ZMK_INPUT_PROCESSOR_TRANSFORM app PRIVATE input_proc
target_sources_ifdef(CONFIG_ZMK_INPUT_PROCESSOR_SCALER app PRIVATE input_processor_scaler.c)
target_sources_ifdef(CONFIG_ZMK_INPUT_PROCESSOR_TEMP_LAYER app PRIVATE input_processor_temp_layer.c)
target_sources_ifdef(CONFIG_ZMK_INPUT_PROCESSOR_CODE_MAPPER app PRIVATE input_processor_code_mapper.c)
+target_sources_ifdef(CONFIG_ZMK_INPUT_PROCESSOR_OUT_OF_BAND_BEHAVIORS app PRIVATE input_processor_out_of_band_behaviors.c)
target_sources_ifdef(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING app PRIVATE resolution_multipliers.c)
target_sources_ifdef(CONFIG_ZMK_INPUT_SPLIT app PRIVATE input_split.c)
diff --git a/app/src/pointing/Kconfig b/app/src/pointing/Kconfig
index 42cf8e8c072..a10168f8a62 100644
--- a/app/src/pointing/Kconfig
+++ b/app/src/pointing/Kconfig
@@ -57,6 +57,11 @@ config ZMK_INPUT_PROCESSOR_CODE_MAPPER
default y
depends on DT_HAS_ZMK_INPUT_PROCESSOR_CODE_MAPPER_ENABLED
+config ZMK_INPUT_PROCESSOR_OUT_OF_BAND_BEHAVIORS
+ bool "Out-Of-Band Behaviors Input Processor"
+ default y
+ depends on DT_HAS_ZMK_INPUT_PROCESSOR_OUT_OF_BAND_BEHAVIORS_ENABLED
+
config ZMK_INPUT_SPLIT
bool "Split input support"
default y
diff --git a/app/src/pointing/input_processor_out_of_band_behaviors.c b/app/src/pointing/input_processor_out_of_band_behaviors.c
new file mode 100644
index 00000000000..8476b3a3cb1
--- /dev/null
+++ b/app/src/pointing/input_processor_out_of_band_behaviors.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_input_processor_out_of_band_behaviors
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#include
+#include
+
+struct ip_oobb_config {
+ size_t size;
+ uint16_t type;
+
+ const uint16_t *codes;
+ const struct zmk_behavior_binding *bindings;
+};
+
+static int ip_oobb_handle_event(const struct device *dev, struct input_event *event,
+ uint32_t param1, uint32_t param2,
+ struct zmk_input_processor_state *state) {
+ const struct ip_oobb_config *cfg = dev->config;
+
+ LOG_DBG("OH");
+
+ if (event->type != cfg->type) {
+ return 0;
+ }
+
+ for (size_t i = 0; i < cfg->size; i++) {
+ if (cfg->codes[i] == event->code) {
+ struct zmk_behavior_binding_event behavior_event = {
+ .position = INT32_MAX,
+ .timestamp = k_uptime_get(),
+#if IS_ENABLED(CONFIG_ZMK_SPLIT)
+ .source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL,
+#endif
+ };
+
+ LOG_DBG("FOUND A MATCHING CODE, invoke %s", cfg->bindings[i].behavior_dev);
+ int ret = zmk_behavior_invoke_binding(&cfg->bindings[i], behavior_event, event->value);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return ZMK_INPUT_PROC_STOP;
+ }
+ }
+
+ return 0;
+}
+
+static struct zmk_input_processor_driver_api ip_oobb_driver_api = {
+ .handle_event = ip_oobb_handle_event,
+};
+
+static int ip_oobb_init(const struct device *dev) { return 0; }
+
+#define ENTRY(i, node) ZMK_KEYMAP_EXTRACT_BINDING(i, node)
+
+#define IP_OOBB_INST(n) \
+ static const uint16_t ip_oobb_codes_##n[] = DT_INST_PROP(n, codes); \
+ static const struct zmk_behavior_binding ip_oobb_bindings_##n[] = { \
+ LISTIFY(DT_INST_PROP_LEN(n, bindings), ZMK_KEYMAP_EXTRACT_BINDING, (, ), DT_DRV_INST(n))}; \
+ BUILD_ASSERT(ARRAY_SIZE(ip_oobb_codes_##n) == ARRAY_SIZE(ip_oobb_bindings_##n), \
+ "codes and bindings need to be the same length"); \
+ static const struct ip_oobb_config ip_oobb_config_##n = { \
+ .type = DT_INST_PROP_OR(n, type, INPUT_EV_KEY), \
+ .size = DT_INST_PROP_LEN(n, codes), \
+ .codes = ip_oobb_codes_##n, \
+ .bindings = ip_oobb_bindings_##n, \
+ }; \
+ DEVICE_DT_INST_DEFINE(n, &ip_oobb_init, NULL, NULL, &ip_oobb_config_##n, POST_KERNEL, \
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &ip_oobb_driver_api);
+
+DT_INST_FOREACH_STATUS_OKAY(IP_OOBB_INST)
\ No newline at end of file
diff --git a/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/events.patterns b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/events.patterns
new file mode 100644
index 00000000000..7374badf0f3
--- /dev/null
+++ b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_mouse_//p
+s/.*hid_listener_keycode_//p
\ No newline at end of file
diff --git a/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/keycode_events.snapshot b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/keycode_events.snapshot
new file mode 100644
index 00000000000..7ad856db606
--- /dev/null
+++ b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/keycode_events.snapshot
@@ -0,0 +1,6 @@
+pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
+released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
+pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
+released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
+pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
+released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
diff --git a/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/native_posix_64.conf b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/native_posix_64.conf
new file mode 100644
index 00000000000..fa514727ba5
--- /dev/null
+++ b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/native_posix_64.conf
@@ -0,0 +1,6 @@
+CONFIG_GPIO=n
+CONFIG_ZMK_BLE=n
+CONFIG_LOG=y
+CONFIG_LOG_BACKEND_SHOW_COLOR=n
+CONFIG_ZMK_LOG_LEVEL_DBG=y
+CONFIG_ZMK_POINTING=y
diff --git a/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/native_posix_64.keymap b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/native_posix_64.keymap
new file mode 100644
index 00000000000..ed4f43817bb
--- /dev/null
+++ b/app/tests/pointing/mouse-move/processors/out_of_bound_behaviors/native_posix_64.keymap
@@ -0,0 +1,44 @@
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+
+&zip_out_of_band_button_behaviors {
+ bindings = <&kp A &kp B &kp C>;
+};
+
+&mkp_input_listener {
+ input-processors = <&zip_out_of_band_button_behaviors>;
+};
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &mkp LCLK &mkp RCLK
+ &mkp MCLK &none
+ >;
+ };
+ };
+};
+
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ ZMK_MOCK_PRESS(0,1,10)
+ ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_PRESS(1,0,10)
+ ZMK_MOCK_RELEASE(1,0,10)
+ >;
+};
\ No newline at end of file
diff --git a/docs/docs/keymaps/input-processors/out-of-band-behaviors.md b/docs/docs/keymaps/input-processors/out-of-band-behaviors.md
new file mode 100644
index 00000000000..71c6eb098cc
--- /dev/null
+++ b/docs/docs/keymaps/input-processors/out-of-band-behaviors.md
@@ -0,0 +1,75 @@
+---
+title: Out-of-Band Behaviors Input Processor
+sidebar_label: Out-of-Band Behaviors
+---
+
+## Overview
+
+The out-of-band behaviors input processor is used invoke standard behaviors when certain input events occur; most frequently this is used to trigger behaviors when certain mouse buttons are triggered by physical pointing devices.
+
+:::note
+
+Because the out-of-band behaviors input processor does not trigger behavior as part of a keymap, some complex behaviors like hold-taps will not work well with this input processor.
+
+:::
+
+## Usage
+
+When used, this input processor takes no parameters, as the event code to behavior mapping is specified in the definition of the specific processor instance, e.g.:
+
+```dts
+&zip_out_of_band_button_behaviors
+```
+
+## Pre-Defined Instances
+
+One pre-defined instance of the out-of-band behaviors input processor is available:
+
+| Reference | Description |
+| ----------------------------------- | -------------------------------------------------- |
+| `&zip_out_of_band_button_behaviors` | Maps left/right/middle clicks to a given behavior. |
+
+Should you with to update the existing instance to trigger different behaviors for each mouse button, you can override the `bindings` property, e.g.:
+
+```dts
+&zip_out_of_band_button_behaviors {
+ bindings = <&kp A &kp B &kp C>;
+};
+```
+
+## User-Defined Instances
+
+Users can define new instances of the out-of-band behaviors input processor if they want to target different codes or assign different behaviors.
+
+### Example
+
+Below example maps the left mouse button code to the middle mouse button.
+
+```dts
+#include
+
+/ {
+ input_processors {
+ zip_right_click_trigger_paste: zip_right_click_trigger_paste {
+ compatible = "zmk,input-processor-out-of-band-behaviors";
+ #input-processor-cells = <0>;
+ codes = ;
+ bindings = <&kp LC(V) >;
+ };
+ };
+}
+```
+
+### Compatible
+
+The code mapper input processor uses a `compatible` property of `"zmk,input-processor-out-of-band-behaviors"`.
+
+### Standard Properties
+
+- `#input-processor-cells` - required to be constant value of `<0>`.
+
+### User Properties
+
+- `type` - The [type](https://github.com/zmkfirmware/zephyr/blob/v3.5.0%2Bzmk-fixes/include/zephyr/dt-bindings/input/input-event-codes.h#L25) of events to scale. Usually, this is `INPUT_EV_KEY` for key/button events. The default value if omitted is `INPUT_EV_KEY`.
+- `codes` - The specific codes of the given type to capture, e.g. [button event codes](https://github.com/zmkfirmware/zephyr/blob/v3.5.0%2Bzmk-fixes/include/zephyr/dt-bindings/input/input-event-codes.h#L180). This list must be the same length as the `bindings` property.
+- `bindings` - The bindings to trigger when an event with the corresponding code is processed.