Linux daemon for Stream Deck control without GUI through filesystem
Project description
deckfs
A Linux daemon for controlling Stream Deck devices without GUI through filesystem interface.
Overview
deckfs provides a simple, filesystem-based interface for configuring and controlling Elgato Stream Deck devices on Linux. Instead of requiring a GUI application, it monitors a directory structure where each numbered folder corresponds to a Stream Deck button.
Features
- Filesystem-based configuration - No GUI required
- Hot reload - Changes take effect immediately without restart
- Multi-format support - PNG, JPEG images and shell/Python/Node.js scripts
- Symbolic link support - Dynamic image switching
- Automatic script detection - Supports .sh, .py, .js action scripts
- Live monitoring - Real-time file system change detection
Installation
From PyPI (when available)
pip install deckfs
From source
git clone https://github.com/spinogrizz/deckfs.git
cd deckfs
pip install .
Quick Start
- Initialize configuration structure:
deckfs setup
- Add images and scripts to button folders:
# Button 1
cp my-icon.png ~/.local/streamdeck/01/image.png
echo '#!/bin/bash\necho "Button 1 pressed!"' > ~/.local/streamdeck/01/action.sh
chmod +x ~/.local/streamdeck/01/action.sh
# Button 2
cp another-icon.jpg ~/.local/streamdeck/02/image.png
echo 'print("Button 2 pressed!")' > ~/.local/streamdeck/02/action.py
- Start the daemon:
deckfs start
Development
Configuration Structure
~/.local/streamdeck/
├── 01/
│ ├── image.png # Button image (PNG/JPEG)
│ └── action.sh # Action script (optional)
├── 02/
│ ├── image.jpg
│ └── action.py
├── 03/
│ ├── image.png
│ └── action.js
└── ...
Folder Naming
- Folders must be named with zero-padded numbers:
01,02,03, etc. - Each folder corresponds to a Stream Deck button position
Images
- Supported formats: PNG, JPEG
- Filename must start with "image" (e.g.,
image.png,image.jpg) - Images are automatically scaled to fit button size
- Symbolic links supported for dynamic switching
Action Scripts
- Optional executable scripts triggered on button press
- Supported types:
.sh- Shell scripts (executed with bash).py- Python scripts (executed with python3).js- JavaScript scripts (executed with node)
- Must be named
action.{extension} - Must be executable for shell scripts
CLI Usage
# Initialize configuration structure
deckfs setup
# Start daemon in foreground
deckfs start
# Start daemon in background
deckfs start --daemon
# Stop running daemon
deckfs stop
# Check daemon status
deckfs status
# Use custom config directory
deckfs start --config-dir /path/to/config
# Show version
deckfs --version
Requirements
- Linux operating system
- Python 3.8+
- Connected Elgato Stream Deck device
- Appropriate udev rules for device access
Device Permissions
You may need to set up udev rules for device access:
# Create udev rule file
sudo tee /etc/udev/rules.d/50-streamdeck.rules << EOF
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", TAG+="uaccess"
EOF
# Reload udev rules
sudo udevadm control --reload-rules
sudo udevadm trigger
Examples
See the examples/ directory for comprehensive examples in different programming languages:
- 01_toggle_mute (Bash) - Toggle system audio mute with visual feedback
- 02_launch_firefox (Python) - Smart Firefox launcher with profile support
- 03_next_track (JavaScript) - Advanced media player control via D-Bus
Each example includes detailed setup instructions, documentation, and demonstrates different integration approaches.
Quick Dynamic Image Switching
# Create images
cp status-online.png ~/.local/streamdeck/01/online.png
cp status-offline.png ~/.local/streamdeck/01/offline.png
# Switch between them using symlinks
ln -sf online.png ~/.local/streamdeck/01/image.png # Shows online
ln -sf offline.png ~/.local/streamdeck/01/image.png # Shows offline
Troubleshooting
Device Not Found
- Ensure Stream Deck is connected and powered
- Check udev rules are properly configured
- Verify user permissions for USB device access
Images Not Updating
- Check file permissions and ownership
- Ensure filename starts with "image"
- Verify image format is PNG or JPEG
Scripts Not Executing
- Verify script has executable permissions (
chmod +x) - Check script interpreter is installed (bash/python3/node)
- Review daemon output for error messages
Development
Project Structure
src/
├── cli.py # Main CLI entry point
├── core/
│ └── daemon.py # Daemon implementation
├── handlers/
│ └── file_handler.py # File system event handling
└── utils/
├── config.py # Configuration constants
└── device.py # Stream Deck device management
Dependencies
streamdeck- Stream Deck SDKPillow- Image processingwatchdog- File system monitoring
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Support
- Report issues: https://github.com/spinogrizz/deckfs/issues
- Source code: https://github.com/spinogrizz/deckfs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deckfs-0.1.2.tar.gz.
File metadata
- Download URL: deckfs-0.1.2.tar.gz
- Upload date:
- Size: 37.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20d483d042acbc9f24ee3153bc20461508e64b91e984859ef32b2717213efb2c
|
|
| MD5 |
8c8a3195a824ae32222ea524b1af4d10
|
|
| BLAKE2b-256 |
86c9ea54cb239ca9693eef2adefaab55f20d6daf511c66231062da616d3cc4db
|
Provenance
The following attestation bundles were made for deckfs-0.1.2.tar.gz:
Publisher:
release.yml on spinogrizz/deckfs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deckfs-0.1.2.tar.gz -
Subject digest:
20d483d042acbc9f24ee3153bc20461508e64b91e984859ef32b2717213efb2c - Sigstore transparency entry: 239353496
- Sigstore integration time:
-
Permalink:
spinogrizz/deckfs@03b97ffb02b74cfa81adb11e8a8e2c9ce2b9a6b2 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/spinogrizz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@03b97ffb02b74cfa81adb11e8a8e2c9ce2b9a6b2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file deckfs-0.1.2-py3-none-any.whl.
File metadata
- Download URL: deckfs-0.1.2-py3-none-any.whl
- Upload date:
- Size: 33.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
daf4b83f7b5250101193a71f30a14f0475fc5635456d3d9123d58e02d573f875
|
|
| MD5 |
58a3b875405e2dc1329e60eb7af4e540
|
|
| BLAKE2b-256 |
10e24897a3479daf580cf1ea1334f9a3afe0b27800dd13f36a8fad75d12f29f6
|
Provenance
The following attestation bundles were made for deckfs-0.1.2-py3-none-any.whl:
Publisher:
release.yml on spinogrizz/deckfs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deckfs-0.1.2-py3-none-any.whl -
Subject digest:
daf4b83f7b5250101193a71f30a14f0475fc5635456d3d9123d58e02d573f875 - Sigstore transparency entry: 239353505
- Sigstore integration time:
-
Permalink:
spinogrizz/deckfs@03b97ffb02b74cfa81adb11e8a8e2c9ce2b9a6b2 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/spinogrizz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@03b97ffb02b74cfa81adb11e8a8e2c9ce2b9a6b2 -
Trigger Event:
push
-
Statement type: