# StreamController: a Linux control surface for the Elgato Stream Deck

> StreamController is a GTK4 and Python application for the Elgato Stream Deck that adds a plugin store, per-page wallpapers, a custom screen saver, automatic page switching driven by the active window, auto-lock, sticky actions, and a command line and D-Bus interface that can drive the deck without the UI running. It is GPL-3.0 licensed, in beta, and the last push was on 2026-09-21.

**StreamController/StreamController** — An elegant Linux app for the Elgato Stream Deck with support for plugins

- Repository: https://github.com/StreamController/StreamController
- Website: https://core447.com
- Stars: 1,146 · Forks: 128
- Language: Python
- License: GPL-3.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/streamcontroller-streamcontroller

## A native Linux alternative for a device whose software is not

StreamController is described as an elegant Linux application designed for the Elgato Stream Deck, offering advanced features like plug-ins and automatic page switching to enhance your streaming and productivity setup.

The word elegant is doing some work there, but the positioning is clear once you look at the rest of the readme. The application is unofficial and not affiliated with Elgato in any way, and the project's own website is core447.com. What that means in practice is that this is a third-party reimplementation of the configuration surface for a piece of hardware whose first-party software is Windows and macOS only.

The hardware support list is long, and it covers the whole Elgato range: Stream Deck Original, Mini, Mini Discord Edition, XL, Pedal, Plus, Plus XL, Neo, Studio and Modules.

Support for devices from other manufacturers is experimental, and two are named with a specific caveat: the Mirabox Stream Dock 293S and the Ulanzi Stream Controller D200, both with no hotplug support yet, so you have to connect the device before starting the app. That caveat is the kind of detail that distinguishes a real testing matrix from a wish list, and it tells you the device discovery layer has a per-device path.

The project distributes through Flathub as `com.core447.StreamController`, and the readme carries the Flathub downloads and version badges. It is written in Python with GTK4, which the topics confirm, and the badges say Made with Python and GPL v3.

The last push was on 2026-09-21, the release tags are 1.5.0-beta.16 from 2026-08-16, 1.5.0-beta.15 from 2026-07-09 and 1.5.0-beta.14 from 2026-05-21, and the project states plainly that it is currently in beta and asks for issue reports.

## Page switching driven by the active window is the feature nobody else has

The automatic page switching feature is the one that distinguishes this from a configuration utility, and its implementation is described in enough detail to be useful.

It is available for GNOME, using the project's own GNOME Shell extension, for Hyprland, Sway, Mangowm, KDE when kdotool is installed, and all X11 desktops. The feature allows you to automatically change your active page based on the active window, with the examples given being switching to your favourite music albums when you open Spotify, your projects when you open VSCode, or your favourite websites in Firefox.

The list of supported environments tells you the implementation approach. A GNOME Shell extension can ask GNOME directly which window is focused, and Hyprland and Sway have their own IPC. For KDE the feature needs kdotool installed, which is a tool that fakes input, and for all X11 desktops the same approach is used. So the general case is a window title match, and each desktop environment is a different way of asking the question.

The auto-lock feature is related and works the other way round. It locks your Stream Deck when your system is locked, preventing unwanted use from third parties, and it works on every session where systemd-logind reports the lock, with dedicated support for Hyprland, GNOME, KDE and Cinnamon.

That distinction between the two features is instructive. Page switching needs to know which application is in the foreground, which is a question only the desktop environment can answer. Auto-lock needs to know whether the session is locked, which is a question systemd-logind can answer, and the project is right to say that it works on every session where logind reports the lock.

The sticky actions feature is smaller and addresses a real annoyance. If you want your special party mode button on all your pages, sticky actions let you do that without copying it to every page manually.

## A command line and a D-Bus API, and pages you can edit with the app closed

The scripting story is the most developed part of the project and the least common thing a Stream Deck configuration tool offers.

StreamController can be scripted. While the app is running you can switch pages, change states, emulate button presses, set the brightness or put a deck to sleep, and you can read back the current devices, pages and actions, with `--json` for machine-readable output. Pages can also be created, renamed, duplicated, exported and edited, including labels, icons, background colors and states, without the app running at all.

The three examples in the readme show the shape of the interface:

```sh
flatpak run com.core447.StreamController --list-devices --json
flatpak run com.core447.StreamController --change-page ABC12345678 "Gaming"
flatpak run com.core447.StreamController --set-label "Gaming" 0,0 0 center text "Play"
```

The `--list-devices --json` form is a machine-readable inventory, the `--change-page` takes a device identifier and a page name, and the `--set-label` takes a page, a coordinate pair, a state, an alignment, a content type and the text. That last one is essentially a scriptable version of dragging a label onto a key.

Run it with `--help` for the full list. Everything is also available over the D-Bus API at `com.core447.StreamController`, so external tools can integrate with StreamController directly.

The two capabilities together are what make this more than a GUI. The command line is how you drive it from a keybinding or a script, and the D-Bus API is how another application talks to it. The offline editing is the third piece: because a page is data, a page can be created and edited by a script with no application running and no device connected, which is what makes it possible to keep page layouts in a repository and generate them from a template.

The other user-facing features are more conventional but worth naming. There is plugin support with a built-in store to download actions, and you can publish your own plugins, with details in the wiki. You can customize your Stream Deck pages with wallpapers and videos. And you can set up a custom screen saver to display a picture or video when the Stream Deck is idle.

## A Flatpak-first project with a Python dependency list to match

The distribution model is Flatpak, and the way it is set up tells you what the project expects of its users.

To install the head of main as a Flatpak you run:

```sh
bash -c "$(wget -O - https://raw.githubusercontent.com/StreamController/StreamController/main/flatpak/install.sh)"
```

And the Flathub listing carries the stable build. There are also unofficial packages maintained by the community, with a Repology badge showing the packaging status across distributions, and they are described as functional but unofficial.

The repository layout is consistent with a Flatpak-first project. There is a `com.core447.StreamController.yml` at the root, which is the Flatpak manifest, a `flatpak/` directory with the install script, and a `.flatpak/` directory. There is a `requirements.txt` and a `pypi-requirements.yaml`, which is the pattern for a Flatpak whose Python dependencies are fetched from PyPI at build time.

That requirements file is long, and it is the clearest statement of what the application does. Beyond the usual web and packaging libraries, the ones that matter are `PyGObject` and `pycairo` for the GTK bindings, `evdev` and `pyudev` for reading input devices directly, `pulsectl` and `libpulse` for PulseAudio, `python-wayland-extra` for Wayland protocol support, `dasbus` and `dbus-python` for the D-Bus API, `opencv-python` for image processing, `get-video-properties` and `imageio-ffmpeg` for video, `pyusb` for USB devices, `pydantic` for configuration validation, `loguru` for logging, and `memray` for memory profiling, which is a direct response to the memory issue the project admits to.

The rest of the tree is a Python application with a `src/` directory, `main.py` at the root, `autostart.py` for starting with the session, `globals.py`, a `permissons.py` and a `style.css`, a `GtkHelper/` directory, `locales/` for translations, `scripts/`, `tests/`, `docs/`, a `Dev-Planning-Board.md` and a `CLAUDE.md`.

The `udev.rules` file is worth noting. Hotplug support for a USB device needs a udev rule, and its presence is consistent with the readme's mention that the experimental third-party devices lack hotplug, which implies the Elgato devices do have it.

## Where StreamController is the wrong choice

The first case is a macOS or Windows user. This is a Linux application, and its value is that it fills a gap the vendor's own software leaves on that platform. On Windows or macOS the official Stream Deck software exists, and if you are happy with it, this project adds nothing.

The second case is someone who does not own an Elgato Stream Deck. The device support list is long but it is a list of Elgato devices, plus two experimental third-party ones. There is no generic MIDI controller or arbitrary USB HID support, so a Stream Deck is a prerequisite rather than an option.

The third case is a user who needs a stable release. The project says it is currently in beta and asks for issue reports, and the tags are all beta versions of 1.5.0, so the release numbering has not reached 1.0. More concretely, the known issues section names one problem and it is a serious one: high memory can be a problem, and the project says it is actively working to resolve it. For an application that runs continuously in the background on a desktop, a memory leak is not a cosmetic issue, and a Flatpak with a `memray` dependency in its requirements suggests the maintainer is profiling it rather than guessing.

The fourth is a user who wants the setup to be shared. The command line and D-Bus API let you script the deck, and pages can be edited without the app running, but the readme does not describe a way to export a whole configuration to a file you can commit and share, which is what a team sharing a streaming setup would want.

One last note on the plugin system. It is the feature that would make the application more than a Stream Deck configuration tool, and it comes with the usual obligations of any plugin ecosystem: a plugin is code running inside your desktop session with your permissions, and the store is where those plugins come from. The wiki has the details, and that is the place to look before installing plugins from it.

## Conclusion

StreamController fits a Linux user with an Elgato Stream Deck who wants more than the vendor's own software offers, especially the plugin system, the automatic page switching and the scriptable interface. It does not fit a macOS or Windows user, since the app is Linux only, and it does not fit someone who needs a stable release given the beta status and the known high memory issue. Before you install, read the known issues, since high memory is called out as an active problem, and check the device list, because support for devices from other manufacturers is explicitly experimental and lacks hotplug.

## FAQ

### Which Stream Deck models does StreamController support?

The Elgato range is supported, including the Stream Deck Original, Mini, Mini Discord Edition, XL, Pedal, Plus, Plus XL, Neo, Studio and Modules. Support for devices from other manufacturers is experimental, and the Mirabox Stream Dock 293S and the Ulanzi Stream Controller D200 have no hotplug support and must be connected before the app starts.

### How do I install StreamController?

Install the stable build from Flathub as `com.core447.StreamController`, or install the head of main as a Flatpak with `bash -c "$(wget -O - https://raw.githubusercontent.com/StreamController/StreamController/main/flatpak/install.sh)"`. Unofficial community packages also exist for other distributions.

### Can I script StreamController?

Yes. While the app runs you can switch pages, change states, emulate button presses, set the brightness or put a deck to sleep, and read back devices, pages and actions with `--json` for machine-readable output. Everything is also available over the D-Bus API at `com.core447.StreamController`, and pages can be created, renamed, duplicated, exported and edited without the app running.

### What does the automatic page switching in StreamController do?

It changes the active page based on the active window, so the deck can show music controls for Spotify, project shortcuts for VSCode and bookmarks for Firefox. It is available for GNOME through the project's Shell extension, Hyprland, Sway, Mangowm, KDE when kdotool is installed, and all X11 desktops.

## Sources

- [License: GPL-3.0](https://github.com/StreamController/StreamController/blob/main/LICENSE)
- [Project website](https://core447.com)
- [README](https://github.com/StreamController/StreamController/blob/main/README.md)
- [Releases](https://github.com/StreamController/StreamController/releases)
- [StreamController/StreamController on GitHub](https://github.com/StreamController/StreamController)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/streamcontroller-streamcontroller
