Open-source project
ShadowBlip/InputPlumber avatar
ShadowBlip/InputPlumber

InputPlumber turns any pile of input devices into one virtual device

Open source input router and remapper daemon for Linux

602 stars94 forksRustGPL-3.0

At a glance

What is it?
InputPlumber is a Rust daemon for Linux that combines gamepads, mice and keyboards, translates their input into virtual mouse, keyboard and gamepad devices, and exposes control over DBus. The one feature on its list that is not done is routing input over the network.
Who is it for?
InputPlumber suits a Linux user with a crowded desk who wants a gamepad to drive a launcher, a trackball to act as a mouse and a keyboard to trigger overlays through a single profile system and one control surface. It does not suit someone who needs to share input between machines, because routing input over the network is still an open item on the feature list, and it does not suit a user who wants a plain evdev remapper with no daemon and no DBus.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Many devices in, one virtual device out

InputPlumber is an open source input routing and control daemon for Linux. The core idea is in the first two lines of its description: it combines any number of input devices, gamepads, mice and keyboards for example, and translates their input into a variety of virtual device formats. That is a different job from a keyboard remapper, which changes one device into another one to one mapping, and a different job again from a macro pad, which sends fixed sequences. Here the source devices and the target device are separate concepts, and the daemon sits between them. The applications upstream of it see a single clean device, and the person configuring it decides which physical input goes where.

The feature list has one open item, and it matters

Four of the five boxes in the feature list are ticked. The daemon can combine multiple input devices, emulate mouse, keyboard and gamepad inputs, intercept and route input over DBus for overlay interface control, and apply input mapping profiles that translate source input into the desired target input. The fifth box, routing input over the network, is unticked. For a Linux desktop tool that is an understandable boundary, since the daemon is a local service talking to local devices, and it keeps the security story simpler than a network protocol would. It does mean the tool is for one machine. A second limitation follows from the same architecture: the daemon has to see raw input, so it needs higher privileges over the input devices, and the permission model is not optional decoration. The project ships a polkit policy alongside the binary for exactly this reason.

Profiles, capability maps and device definitions are all data files

The interesting part of the packaging metadata is how much of the behaviour is described in YAML and JSON rather than in code. The RPM asset list shows device definitions written to /usr/share/inputplumber/devices, schema files for those definitions, capability maps, and profiles, each family in its own directory. A capability map is the translation table between what a physical device can do and what the virtual device exposes, and a profile is the rule set that says which source input becomes which target input. Keeping them as data means a user can add a device or change a mapping without recompiling, and it means the schema files can be used to validate a file before the daemon tries to load it. The package also ships a udev hardware database fragment, so device identification happens at the system level rather than only inside the daemon.

DBus is the control surface

Control of InputPlumber happens over DBus, and the documentation has a page dedicated to the DBus API, with the composite device as its example. The package registers a system bus configuration file named org.shadowblip.InputPlumber.conf, which is the same name the Makefile uses for its DBUS_NAME variable, so the bus name and the service are wired together. That design is what makes the third feature work: intercepting and routing input so an overlay interface can drive it. The typical arrangement is a companion application speaking to the daemon over the bus, asking it to switch input targets or to route a button to something else, without touching the user session directly. It also means the daemon is not a setuid mystery process, because the permission decision belongs to polkit.

The RPM carries services, policies and data in one asset list

The rpm packaging metadata in Cargo.toml is a compact picture of how the project installs itself, and it is worth reading as a design document. The binary goes to /usr/bin/inputplumber, the DBus system configuration to the system bus directory, the polkit action and the polkit rules to their standard locations, two systemd unit files to /usr/lib/systemd/system, and then the data directories for devices, schemas, capability maps and profiles. The two units are inputplumber.service and inputplumber-suspend.service, and the second one exists to handle suspend and resume, which is the kind of edge case that shows up in a daemon that owns a device. The asset list for one entry shows the pattern, with a source path, a destination and a mode.

toml
  { source = "target/release/inputplumber", dest = "/usr/bin/inputplumber", mode = "755" },
  { source = "rootfs/usr/share/dbus-1/system.d/org.shadowblip.InputPlumber.conf", dest = "/usr/share/dbus-1/system.d/org.shadowblip.InputPlumber.conf", mode = "644" },

The rest of the list follows the same shape for the polkit action, the polkit rules, the two systemd units, the four data directories and the udev fragment. Nothing in the list is a configuration file that the user is expected to edit in place, which is a sane choice for something that a package manager will overwrite on upgrade.

Building it: a Makefile that reads Cargo.toml and a Dockerfile that cross compiles

The build has two halves, and the Makefile is the part that is unusual. It does not hardcode the package name or the version, it reads them out of the Cargo.toml at build time, and it derives the target architecture from the Rust compiler itself.

make
DBUS_NAME := org.shadowblip.InputPlumber
PREFIX ?= /usr
CACHE_DIR := .cache
ENABLE_METRICS ?= 1
BUILD_TYPE ?= release
LOG_LEVEL ?= debug
IMAGE_NAME ?= inputplumber-builder
IMAGE_TAG ?= latest
SYSEXT_ID ?= _any
-include settings.mk

The first two lines of that file are the interesting part, because the package name and the version are grepped out of Cargo.toml rather than duplicated, so there is one source of truth for the version. The systemd-sysext variables show a second distribution route in the works, a self extending image that does not need a normal package install. The build itself runs in a container, and the Dockerfile is set up for a cross compile to 64-bit arm hardware on top of a Rust 1.92 base image.

dockerfile
FROM rust:1.92

RUN dpkg --add-architecture arm64
RUN apt-get update && apt-get install -y \
  zstd \
  libclang-dev \
  libudev-dev \
  squashfs-tools

The rest of that file adds the arm64 cross compiler, installs the aarch64 Rust target and a matching toolchain, and points the linker and the C and C++ compilers at the cross toolchain.

Rust, GPL-3.0+, and releases every few weeks

The crate is named inputplumber, at version 0.82.0, on the 2021 edition of Rust, and it is licensed GPL-3.0-or-later with two named authors, William Edwards and Derek J. Clark. The release record shows a steady cadence: v0.80.0 and v0.81.0 both on 2026-09-14 and v0.82.0 on 2026-10-10, with the last push on 2026-10-19. The documentation is published from the repository itself, with an overview, an installation page, a usage page and the DBus API section, and the project also exposes a readthedocs site. There is a contributing guide, a release configuration, an examples directory holding a unified_gamepad example, and a bindings directory, which suggests the project intends to be driven from other languages as well as from its own Rust code.

Editorial conclusion

InputPlumber suits a Linux user with a crowded desk who wants a gamepad to drive a launcher, a trackball to act as a mouse and a keyboard to trigger overlays through a single profile system and one control surface. It does not suit someone who needs to share input between machines, because routing input over the network is still an open item on the feature list, and it does not suit a user who wants a plain evdev remapper with no daemon and no DBus. Before you rely on it, read the installation page in the documentation, check the polkit action that the RPM ships, and run the unified_gamepad example to see how the source to target translation is meant to be expressed.

Frequently asked questions

What does InputPlumber do on Linux?

It is an input routing and control daemon that combines any number of input devices such as gamepads, mice and keyboards and translates their input into virtual device formats. It can emulate mouse, keyboard and gamepad input, and it applies input mapping profiles that translate source input into the target input.

Can InputPlumber send input over the network?

Not yet. Routing input over the network is the one item on the feature list that is still unticked, so the daemon is a local service for a single machine.

How is InputPlumber controlled?

Over DBus. The project ships a system bus configuration named org.shadowblip.InputPlumber.conf and documents a DBus API with a composite device as the worked example, which is how overlay interfaces intercept and route input. Permissions are handled with a shipped polkit action and rules.

Where are InputPlumber's mappings stored?

As data files rather than code. The RPM installs device definitions, schema files, capability maps and profiles as YAML and JSON under /usr/share/inputplumber, and a udev hardware database fragment is shipped as well, so devices and mappings can be added without recompiling.

Official sources

  1. License: GPL-3.0
  2. Project website
  3. README
  4. Releases
  5. ShadowBlip/InputPlumber on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/shadowblip-inputplumber.svg)](https://hysenlabs.com/projects/shadowblip-inputplumber)