deckmaster

command module
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 48 Imported by: 0

README

deckmaster

Latest Release Go Doc Software License Build Status Go ReportCard

An application to control your Elgato Stream Deck on Linux

Features

  • Multiple pages & navigation between decks
  • Buttons (icons & text)
  • Background images
  • Brightness control
  • Supports different actions for short & long presses
  • Supports all Stream Deck models, including:
    • Stream Deck+ and + XL dials and touch screen
    • Stream Deck Studio dials with LED rings
    • Stream Deck Neo touch keys and info screen
    • Stream Deck Pedal
  • Comes with a collection of widgets:
    • Buttons
    • Time (with formatting)
    • CPU/Mem usage
    • Weather
    • Command output
    • Recently used windows (X11-only)
  • Lets you trigger several actions:
    • Run commands
    • Emulate a key-press
    • Paste to clipboard
    • Trigger a dbus call

Supported Devices

Device Keys Other controls
Stream Deck Original, MK.2, Module 15 Keys (all revisions) 5×3
Stream Deck Mini, Module 6 Keys (all revisions) 3×2
Stream Deck XL, Module 32 Keys (all revisions) 8×4
Stream Deck+ 4×2 4 dials, touch screen
Stream Deck + XL* 9×4 6 dials, touch screen
Stream Deck Neo* 4×2 2 touch keys with LEDs, info screen
Stream Deck Studio* 16×2 (144×112 pixels) 2 dials with LED rings
Stream Deck Pedal* 3 pedals

* Support for these models follows the reference implementations of their protocol, but hasn't been tested on hardware yet. Please report how it works!

Installation

Packages
From source

Make sure you have a working Go environment (Go 1.26 or higher is required). See the install instructions.

To install deckmaster, simply run:

git clone https://github.com/nix-er/deckmaster.git
cd deckmaster
go build

Or install it directly with:

go install github.com/nix-er/deckmaster@latest

Building requires cgo (a C compiler) for USB access.

Nix

The repository is a Nix flake. To run deckmaster without installing it:

nix run github:nix-er/deckmaster -- -deck main.deck

To add it to a NixOS configuration, add the flake as an input and use its package. The package also ships the udev rules described below:

{
  inputs.deckmaster.url = "github:nix-er/deckmaster";

  # in your NixOS module:
  environment.systemPackages = [ inputs.deckmaster.packages.${pkgs.stdenv.hostPlatform.system}.default ];
  services.udev.packages = [ inputs.deckmaster.packages.${pkgs.stdenv.hostPlatform.system}.default ];
}

nix develop opens a shell with Go, a C compiler, golangci-lint and goreleaser.

System Setup

On Linux you need to set up some udev rules to be able to access the device as a regular user. Copy udev/70-streamdeck.rules to /etc/udev/rules.d/ (on NixOS, use services.udev.packages as shown above):

sudo cp udev/70-streamdeck.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger

The rules use TAG+="uaccess", which gives the user logged in on the local seat access to the device, so no extra group membership is needed. The file name must sort before 73-seat-late.rules, or uaccess has no effect. Unplug and re-plug the device, and you should be good to go.

To emulate key presses, deckmaster also needs write access to /dev/uinput; see the commented rule at the end of the file.

Starting deckmaster automatically

If you want deckmaster to be started automatically upon device plugin, you can use systemd path activation, adding streamdeck.path and streamdeck.service files to $HOME/.config/systemd/user.

streamdeck.path contents:

[Unit]
Description="Stream Deck Device Path"

[Path]
# /dev/streamdeck is created by the optional SYMLINK rule at the end of
# udev/70-streamdeck.rules
PathExists=/dev/streamdeck
Unit=streamdeck.service

[Install]
WantedBy=default.target

streamdeck.service contents:

[Unit]
Description=Deckmaster Service

[Service]
# adjust the path to deckmaster and .deck file to suit your needs
ExecStart=/usr/local/bin/deckmaster --deck path-to/some.deck
Restart=on-failure
ExecReload=kill -HUP $MAINPID

[Install]
WantedBy=default.target

Then enable and start the streamdeck.path unit:

systemctl --user enable streamdeck.path
systemctl --user start streamdeck.path

Usage

Start deckmaster with the initial deck configuration you want to load:

deckmaster -deck deck/main.deck

You can control the brightness, in percent:

deckmaster -brightness 50

Control a specific streamdeck:

deckmaster -device [serial number]

Set a sleep timeout after which the screen gets turned off:

deckmaster -sleep 10m

Configuration

You can find a few example configurations in the decks directory. Edit them to your needs!

Widgets

Any widget is build up the following way:

[[keys]]
  index = 0

index needs to be present in every widget and describes the position of the widget on the streamdeck. index is 0-indexed and counted from top to bottom and left to right.

Update interval for widgets

Optionally, you can configure an update interval for each widget:

[keys.widget]
  id = "button"
  interval = 500 # optional

The attribute interval defines the time in ms between two consecutive updates of a widget.

Button

A simple button that can display an image and/or a label.

[keys.widget]
  id = "button"
  [keys.widget.config]
    icon = "/some/image.png" # optional
    label = "My Button" # optional
    fontsize = 10.0 # optional
    color = "#fefefe" # optional
    flatten = true # optional

If flatten is true all opaque pixels of the icon will have the color color.

Recent Window (requires X11)

Displays the icon of a recently used window/application. Pressing the button activates the window.

[keys.widget]
  id = "recentWindow"
  [keys.widget.config]
    window = 1
    showTitle = true # optional

If showTitle is true, the title of the window will be displayed below the window icon.

Time

A flexible widget that can display the current time or date.

[keys.widget]
  id = "time"
  [keys.widget.config]
    format = "%H;%i;%s"
    font = "bold;regular;thin" # optional
    color = "#fefefe" # optional
    layout = "0x0+72x24;0x24+72x24;0x48+72x24" # optional

With layout custom layouts can be definded in the format [posX]x[posY]+[width]x[height].

Values for format are:

% gets replaced with
%Y A full numeric representation of a year, 4 digits
%y A two digit representation of a year
%F A full textual representation of a month, such as January or March
%M A short textual representation of a month, three letters
%m Numeric representation of a month, with leading zeros
%l A full textual representation of the day of the week
%D A textual representation of a day, three letters
%d Day of the month, 2 digits with leading zeros
%h 12-hour format of an hour with leading zeros
%H 24-hour format of an hour with leading zeros
%i Minutes with leading zeros
%s Seconds with leading zeros
%a Lowercase Ante meridiem and Post meridiem
%t Timezone abbreviation
Top

This widget shows the current CPU or memory utilization as a bar graph.

[keys.widget]
  id = "top"
  [keys.widget.config]
    mode = "cpu"
    color = "#fefefe" # optional
    fillColor = "#d497de" # optional

There are two values for mode: cpu and memory.

Command

A widget that displays the output of commands.

[keys.widget]
  id = "command"
  [keys.widget.config]
    command = "echo 'Files:'; ls -a ~ | wc -l"
    font = "regular;bold" # optional
    color = "#fefefe" # optional
    layout = "0x0+72x20;0x20+72x52" # optional
Weather

A widget that displays the weather condition and temperature.

[keys.widget]
  id = "weather"
  [keys.widget.config]
    location = "MyCity" # optional
    unit = "celsius" # optional
    color = "#fefefe" # optional
    flatten = true # optional
    theme = "openmoji" # optional

The supported location types can be found here. The unit has to be either celsius or fahrenheit. If flatten is true all opaque pixels of the condition icon will have the color color. In case theme is set corresponding icons with correct names need to be placed in ~/.local/share/deckmaster/themes/[theme]. The default icons with their respective names can be found here.

Actions

You can hook up any key with several actions. A regular keypress will trigger the widget's configured keys.action, while holding the key will trigger keys.action_hold.

Switch deck
[keys.action]
  deck = "relative/path/to/another.deck"
Run a command
[keys.action]
  exec = "some_command --with-parameters"
Emulate key-presses
[keys.action]
  keycode = "Leftctrl-C"

Emulate a series of key-presses with delay in between:

[keys.action]
  keycode = "Leftctrl-X+500 / Leftctrl-V / Num1"

A list of available keycodes can be found here: keycodes

Paste to clipboard
[keys.action]
  paste = "some text"
Trigger a dbus call
[keys.action.dbus]
  object = "object"
  path = "path"
  method = "method"
  value = "value" # optional

Without a value the method is called without arguments. A plain value is passed as a string; prefix it with a type like dbus-send does to pass something else, e.g. int32:4, uint32:4, int64:4, uint64:4, int16:4, uint16:4, byte:4, double:0.5, boolean:true, objpath:/org/example or string:int32:4 (the string int32:4).

Device actions

Increase the brightness. If no value is specified, it will be increased by 10%:

[keys.action]
  device = "brightness+5"

Decrease the brightness. If no value is specified, it will be decreased by 10%:

[keys.action]
  device = "brightness-5"

Set the brightness to a specific value between 0 and 100:

[keys.action]
  device = "brightness=50"

Put the device into sleep mode, blanking the screen until the next key gets pressed:

[keys.action]
  device = "sleep"
Background Image

You can configure each deck to display an individual wallpaper behind its widgets:

background = "/some/image.png"
Re-using another deck's configuration

If you specify a parent inside a deck's configuration, it will inherit all of the parent's settings that are not overwritten by the deck's own settings. This even works recursively:

parent = "another.deck"

Dials, swipe actions and the info screen widget are inherited the same way.

Dials and touch screen

The Stream Deck+ (four dials) and + XL (six dials) have a touch screen segment above each dial. A dial and its segment are configured together in a [[dials]] entry, with index 0 being the leftmost dial. All settings are optional:

[[dials]]
  index = 0
  # widget shown on the touch screen segment above the dial
  [dials.widget]
    id = "button"
    [dials.widget.config]
      icon = "/some/volume.png"
      label = "Volume"
  # pressing the dial (action_hold for long presses)
  [dials.action]
    keycode = "Mute"
  # turning the dial counterclockwise / clockwise
  [dials.action_left]
    keycode = "VolumeDown"
  [dials.action_right]
    keycode = "VolumeUp"
  # tapping the segment (action_touch_hold for long presses)
  [dials.action_touch]
    exec = "pavucontrol"

All widgets and actions work on dials. Buttons, time and command widgets use the whole segment (a button shows its icon left of its label); the others are drawn as a square in the middle of their segment. The touch screen can't show fine detail, so large icons and short labels work best, e.g. a single line format = "%H:%i" for a clock. A fast turn sends several steps at once; the turn action then runs once per step (at most 10 times), except for deck switches. Tapping a segment without an action_touch triggers the widget's own action (e.g. activating a window for recentWindow).

Swiping across the touch screen can trigger an action, e.g. to switch decks:

[swipe]
  [swipe.left]
    deck = "next.deck"
  [swipe.right]
    deck = "previous.deck"

See decks/plus.deck for a complete example.

Stream Deck Studio dial LEDs

The Stream Deck Studio's two dials have no screen, but an LED ring and a knob LED. Configure them in the [[dials]] entry, next to the dial's actions. The ring can show a value from 0 to 100, printed by a command:

[[dials]]
  index = 0
  ring_color = "#00c060"
  knob_color = "#ffffff"
  # optional: light only part of the ring, e.g. to show the volume
  ring_value = "pamixer --get-volume"
  ring_interval = 1000 # milliseconds, optional

The value command runs every ring_interval milliseconds (every second by default), and right after the dial is turned or pressed. LEDs without a color are turned off. See decks/studio.deck for a complete example.

Stream Deck Neo touch keys and info screen

The Stream Deck Neo's two touch keys have no display, but an LED. They are keys 8 and 9, configured like the other keys with a color instead of a widget:

[[keys]]
  index = 8
  color = "#ff8000"
  [keys.action]
    keycode = "VolumeDown"

Any widget can be shown on the info screen between them (248×58 pixels):

[info.widget]
  id = "time"
  [info.widget.config]
    format = "%H:%i"

See decks/neo.deck for a complete example.

Stream Deck Pedal

The pedals are keys 0 to 2 (left to right). As they have no display, only their actions are used.

More Decks!

Made your own useful decks? Submit a pull request!

Feedback

Got some feedback or suggestions? Please open an issue or drop me a note!

Documentation

Overview

Deckmaster is an application to control Elgato Stream Deck devices on Linux.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL