Agent Skill
2/7/2026

ops-streamdeck

Stream Deck control skill for agents. Provides ability to restart streamdeck daemons, execute button tasks, query status, and manage Stream Deck hardware through a persistent daemon interface. Works with the streamdeck Python package for CLI operations and agent-driven automation.

G
grahama1970
0GitHub Stars
1Views
npx skills add grahama1970/agent-skills

SKILL.md

Nameops-streamdeck
DescriptionStream Deck control skill for agents. Provides ability to restart streamdeck daemons, execute button tasks, query status, and manage Stream Deck hardware through a persistent daemon interface. Works with the streamdeck Python package for CLI operations and agent-driven automation.

name: ops-streamdeck description: > Stream Deck control skill for agents. Provides ability to restart streamdeck daemons, execute button tasks, query status, and manage Stream Deck hardware through a persistent daemon interface. Works with the streamdeck Python package for CLI operations and agent-driven automation. allowed-tools: Bash, Read triggers:

  • restart streamdeck
  • streamdeck button
  • execute streamdeck task
  • streamdeck status
  • streamdeck daemon
  • start streamdeck
  • stop streamdeck
  • streamdeck health check
  • fix streamdeck buttons
  • streamdeck broken metadata: short-description: Stream Deck daemon control and automation

provides:

  • ops-streamdeck composes: [task-monitor]

Stream Deck Skill

Agent-accessible interface for Stream Deck control. Provides persistent daemon management, button task execution, and status querying capabilities.

Architecture

The streamdeck project has two components:

  1. CLI Tool (streamdeck command) - Manual operations by users
  2. Daemon (this skill) - Persistent service for agent automation
┌─────────────────────────────────────────────────────────────────────┐
│                    AGENT / AUTOMATION                          │
│                                                              │
│  ┌────────────────────────────────────────────────────────┐     │
│  │  Stream Deck Skill (this skill)               │     │
│  │  • Restart daemon                              │     │
│  │  • Execute button tasks                        │◄──►│
│  │  • Query status                                 │     │
│  └────────────────────────────────────────────────────────┘     │
│                          │                                   │
│                          ▼                                   │
│  ┌────────────────────────────────────────────────────────┐     │
│  │  Stream Deck Daemon (persistent service)        │     │
│  │  • Manages Stream Deck hardware               │     │
│  │  • Executes button press events                 │     │
│  │  • Provides status API                         │     │
│  └────────────────────────────────────────────────────────┘     │
│                          │                                   │
│                          ▼                                   │
│  ┌────────────────────────────────────────────────────────┐     │
│  │  Stream Deck CLI (manual operations)        │     │
│  │  • User-invoked commands                     │     │
│  │  • Video chat, lights, monitoring, etc.      │     │
│  └────────────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────────────┘

Quick Start

1. Start the Daemon

# Start the streamdeck daemon in the background
./run.sh daemon start

# Or start in foreground for debugging
./run.sh daemon start --foreground

2. Use Agent Commands

# Restart the daemon
./run.sh restart

# Execute a button task
./run.sh button <button_id> [args...]

# Query daemon status
./run.sh status

# List available buttons
./run.sh list-buttons

# Get daemon logs
./run.sh logs

Commands

Daemon Management

CommandDescription
daemon startStart the streamdeck daemon (background)
daemon start --foregroundStart daemon in foreground (for debugging)
daemon stopStop the streamdeck daemon
daemon restartRestart the streamdeck daemon
daemon statusCheck if daemon is running
daemon logsView daemon logs

Button Operations

CommandDescription
button <id>Execute button press event
button <id> --holdExecute button long-press event
list-buttonsList all available button IDs
button-info <id>Get information about a button

Status Queries

CommandDescription
statusGet overall daemon status
status --jsonGet status in JSON format
status --buttonsGet button states

Configuration

CommandDescription
configShow current configuration
config --set <key> <value>Set configuration value
config --get <key>Get configuration value

Prompts Management

CommandDescription
prompts listList available prompts
prompts copy <name>Copy prompt content to clipboard
prompts set-button <name> <btn>Configure a button for a prompt
prompts set-button ... --switch-page NConfigure button to switch page after press (1=Home, 2=Page 1)

Health Check & Auto-Fix

CommandDescription
health-checkVerify all services running and icons correct
fixAuto-repair broken button configurations
# Check if buttons are configured correctly
./run.sh health-check

# Auto-fix broken buttons (stops service, edits config, restarts)
./run.sh fix

CRITICAL: Config File Behavior

The Stream Deck UI (streamdeck.service) saves its in-memory state to ~/.streamdeck_ui.json every ~30 seconds.

NEVER edit the config while the service is running! Your changes will be overwritten.

Correct Procedure for Config Changes

# 1. STOP the service first
systemctl --user stop streamdeck.service

# 2. Edit the config file
vim ~/.streamdeck_ui.json

# 3. START the service (loads your changes into memory)
systemctl --user start streamdeck.service

Why Socket Updates Are Temporary

The icon_updater.py sends updates via Unix socket to change button icons in real-time. These updates modify the in-memory state only. When the service saves its state (every ~30 seconds), it writes the in-memory values back to the config file.

This means:

  • Socket updates appear immediately on the Stream Deck
  • But if the config file had different values, those get overwritten
  • The next time the service restarts, it loads from the config file

Use ./run.sh fix to safely update button configurations.

Configuration

The daemon reads configuration from:

  1. Environment Variables:

    • STREAMDECK_DAEMON_PORT - Port for daemon API (default: 48970)
    • STREAMDECK_DAEMON_HOST - Host for daemon API (default: 127.0.0.1)
    • STREAMDECK_LOG_LEVEL - Log level (DEBUG, INFO, WARNING, ERROR)
  2. Config File: ~/.streamdeck/daemon.json

Example Config

{
  "daemon": {
    "port": 48970,
    "host": "127.0.0.1",
    "log_level": "INFO"
  },
  "buttons": {
    "0": {
      "name": "Video Chat Start",
      "command": "streamdeck videochat start"
    },
    "1": {
      "name": "Video Chat Stop",
      "command": "streamdeck videochat stop"
    },
    "2": {
      "name": "Lights Toggle",
      "command": "streamdeck lights toggle"
    },
    "3": {
      "name": "Time Tracker Toggle",
      "command": "streamdeck time-tracker toggle"
    }
  }
}

Integration with Stream Deck CLI

The daemon works alongside the existing streamdeck CLI:

  • CLI - Used for manual operations by humans
  • Daemon - Used for automated operations by agents
  • Both** share the same configuration and codebase

This dual approach ensures:

  • ✅ Human users can continue using familiar CLI commands
  • ✅ Agents have reliable daemon for automation
  • ✅ No breaking changes to existing functionality
  • ✅ Consistent behavior across both interfaces

API Endpoints

The daemon exposes a simple HTTP API:

EndpointMethodDescription
GET /statusGETGet daemon status
GET /buttonsGETList all buttons
GET /buttons/{id}GETGet button info
POST /buttons/{id}POSTExecute button press
POST /buttons/{id}/holdPOSTExecute button long-press
POST /restartPOSTRestart daemon
POST /stopPOSTStop daemon

Example API Usage

# Get status
curl http://127.0.0.1:48970/status

# Execute button
curl -X POST http://127.0.0.1:48970/buttons/0

# Get button info
curl http://127.0.0.1:48970/buttons/0

Troubleshooting

Daemon Won't Start

# Check if port is already in use
lsof -i :48970

# Check logs for errors
./run.sh logs

# Try starting in foreground to see errors
./run.sh daemon start --foreground

Button Not Executing

# Check button configuration
./run.sh button-info <id>

# Verify daemon is running
./run.sh status

# Check logs for errors
./run.sh logs

Permission Issues

The daemon requires access to:

  • Stream Deck hardware (USB device access)
  • Configuration directory (~/.streamdeck/)
  • Network port (48970) for API

On Linux, ensure user has proper permissions:

# Add user to dialout group (for serial port access)
sudo usermod -a -G dialout $USER

# Ensure ~/.streamdeck is writable
chmod 755 ~/.streamdeck

Development

Running Tests

# Run daemon tests
./sanity.sh

# Run with verbose output
./sanity.sh --verbose

Adding New Features

To add new button commands:

  1. Add button configuration to ~/.streamdeck/daemon.json
  2. Implement command handler in daemon code
  3. Test with: ./run.sh button <id>

Data Storage

  • Config: ~/.streamdeck/daemon.json - Button configurations and daemon settings
  • Logs: ~/.streamdeck/daemon.log - Daemon activity logs
  • State: ~/.streamdeck/daemon.state - Current button states (runtime only)

Dependencies

  • Python 3.8+
  • Stream Deck Python SDK (streamdeck)
  • FastAPI (for daemon API)
  • Uvicorn (for daemon server)
  • Pydantic (for API models)

Install dependencies:

# Via uvx (recommended)
uvx --from "git+https://github.com/grahama1970/streamdeck.git" streamdeck-daemon

# Or manually
pip install streamdeck fastapi uvicorn pydantic

License

MIT License - See LICENSE file for details.

Skills Info
Original Name:ops-streamdeckAuthor:grahama1970