HomeJavaModsCombind
Combind
Combind — screenshot 1Combind — screenshot 2Combind — screenshot 3

This mod expands vanilla keybinds with combo support, letting you bind any action to a chord or a key sequence instead of a single key.

It is client-side only and requires no server-side installation.

Key Binds Screen

Features

Chord Combos

Sequence Combos

Controls Screen Integration

Configuration

Use Cases

This mod shines in modpacks where keys are scarce and every binding needs to be deliberate, but works just as well in vanilla for extra flexibility.

A Practical Example

Double-tap Q (Q Q) (or even triple-tap Q (Q Q Q)!) to drop items instead of a single press. No more accidental drops.

Compatibility

This mod has no required dependencies beyond Fabric API. It works with:


Note: Some niche vanilla interactions are tied to a specific input type and may not work when rebound. For example, a mouse button bound to "Open Inventory" will not close it the way a key would, and a key bound to "Pick Block" will not support block duplication dragging inside containers the way a mouse button would.

Note: If you encounter any compatibility issues, please report them on the GitHub Issues page.


For Mod Developers

Using the Combind API

Combind exposes three API classes under net.pemiridosa.combind.api that let your mod register key bindings with full combo support.

Dependency Setup

Add Combind as a compile-time dependency via the Modrinth Maven repository:

// build.gradle
repositories {
    maven { url "https://api.modrinth.com/maven" }
}

dependencies {
    compileOnly "maven.modrinth:combind:VERSION"
    localRuntime "maven.modrinth:combind:VERSION" // optional: for dev runs
}

Declare the dependency in fabric.mod.json. Use depends if your mod requires Combind, or suggests if it is optional:

"depends": {
    "combind": "*"
}

API Classes

Class Purpose
CombindKeyBinding Wraps a vanilla KeyMapping with combo support — the main entry point
KeyCombo Describes a combo: single key, chord, sequence, or chord + sequence
InputKey Represents one physical input — InputKey.keyboard(glfwCode) or InputKey.mouse(glfwButton)

Examples

Chord — held modifier(s) + trigger key

Bind an action to Left Shift + E:

KeyMapping.Category category = KeyMapping.Category.register(
    Identifier.fromNamespaceAndPath("mymod", "mymod")
);

KeyMapping someActionMapping = KeyMappingHelper.registerKeyMapping(
    new KeyMapping("key.mymod.someaction", GLFW.GLFW_KEY_E, category)
);

// Left Shift + E
CombindKeyBinding someActionBinding = CombindKeyBinding.of(someActionMapping,
    new KeyCombo(
        InputKey.keyboard(GLFW.GLFW_KEY_E),
        new InputKey[]{ InputKey.keyboard(GLFW.GLFW_KEY_LEFT_SHIFT) }
    )
);

someActionBinding
    .onPress(ctx -> LOGGER.info("Some action PRESSED — combo: {}", ctx.combo().getDisplayName()))
    .onRelease(ctx -> LOGGER.info("Some action RELEASED — combo: {}", ctx.combo().getDisplayName()));

Chord with multiple modifiers

Bind an action to Left Control + Left Shift + E:

KeyMapping someActionMapping = KeyMappingHelper.registerKeyMapping(
    new KeyMapping("key.mymod.someaction", GLFW.GLFW_KEY_E, category)
);

// Left Control + Left Shift + E
CombindKeyBinding someActionBinding = CombindKeyBinding.of(someActionMapping,
    new KeyCombo(
        InputKey.keyboard(GLFW.GLFW_KEY_E),
        new InputKey[]{
            InputKey.keyboard(GLFW.GLFW_KEY_LEFT_CONTROL),
            InputKey.keyboard(GLFW.GLFW_KEY_LEFT_SHIFT)
        }
    )
);

someActionBinding
    .onPress(ctx -> LOGGER.info("Some action PRESSED — combo: {}", ctx.combo().getDisplayName()))
    .onRelease(ctx -> LOGGER.info("Some action RELEASED — combo: {}", ctx.combo().getDisplayName()));

Sequence — tap the same key multiple times

Bind an action to M M (double-tap) or M M M (triple-tap):

KeyMapping someActionMapping = KeyMappingHelper.registerKeyMapping(
    new KeyMapping("key.mymod.someaction", GLFW.GLFW_KEY_M, category)
);

// Double-tap M (M M)
CombindKeyBinding someActionBinding = CombindKeyBinding.of(someActionMapping,
    KeyCombo.sequence(InputKey.keyboard(GLFW.GLFW_KEY_M), 2)
);

// Triple-tap M (M M M) — even safer
CombindKeyBinding someActionBinding = CombindKeyBinding.of(someActionMapping,
    KeyCombo.sequence(InputKey.keyboard(GLFW.GLFW_KEY_M), 3)
);

someActionBinding
    .onPress(ctx -> LOGGER.info("Some action PRESSED — combo: {}", ctx.combo().getDisplayName()))
    .onRelease(ctx -> LOGGER.info("Some action RELEASED — combo: {}", ctx.combo().getDisplayName()));

Chord + sequence — hold modifier(s) while multi-tapping

Bind an action to Left Shift + Q Q (double-tap Q while holding Shift):

// Left Shift + Q Q
CombindKeyBinding binding = CombindKeyBinding.of(mapping,
    new KeyCombo(
        InputKey.keyboard(GLFW.GLFW_KEY_Q),
        new InputKey[]{ InputKey.keyboard(GLFW.GLFW_KEY_LEFT_SHIFT) },
        2
    )
);

Mouse button as trigger

Bind an action to Left Control + Left Button:

// Left Control + Left Mouse Button
CombindKeyBinding binding = CombindKeyBinding.of(mapping,
    new KeyCombo(
        InputKey.mouse(GLFW.GLFW_MOUSE_BUTTON_LEFT),
        new InputKey[]{ InputKey.keyboard(GLFW.GLFW_KEY_LEFT_CONTROL) }
    )
);

Single key (no explicit combo needed)

CombindKeyBinding.of(mapping) infers the initial combo from the KeyMapping's default key:

CombindKeyBinding binding = CombindKeyBinding.of(mapping); // defaults to the KeyMapping's key

Unbound — no key assigned by default

// Player must configure this in the Controls > Key Binds screen
CombindKeyBinding binding = CombindKeyBinding.of(mapping, KeyCombo.unbound());

Tick-Based Polling (Vanilla Style)

If you prefer the standard tick-polling pattern instead of callbacks, it works unchanged via the vanilla KeyMapping:

ClientTickEvents.END_CLIENT_TICK.register(client -> {
    while (someActionMapping.consumeClick()) {
        // handle each queued click
    }

    if (someActionMapping.isDown()) {
        // binding is currently held
    }
});

For more details, see the full implementation at src/client/java/net/pemiridosa/combind/api.

Quick facts

Install steps are the general flow for this file type — How to install Minecraft Java mods & modpacks walks through it step by step.

Verified by MCModsHub

These come from our own check of the pack file, not from the source page.

Explore more