Files
home/triggershell.yml
valknarandClaude Sonnet 5 6e60829987 feat(triggershell): add Spotify stop playback command
Pauses Spotify via its MPRIS D-Bus interface. Talks to the user bus
socket directly ($XDG_RUNTIME_DIR/bus) since triggershell.service starts
before the graphical session and lacks DBUS_SESSION_BUS_ADDRESS. No-op
when Spotify is not running.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uCHmJ3PGcHZGtx8mYqmQG
2026-09-09 21:59:55 +02:00

487 lines
14 KiB
YAML

# TriggerShell configuration.
# Full reference: https://dev.pivoine.art/valknar/triggershell.git (see docs/CONFIG_REFERENCE.md)
server:
host: 0.0.0.0
port: 4173
auth:
enabled: true
# Must be >= 32 characters if auth is enabled. Kept out of this file - `triggershell init`
# generated one into .env (TRIGGERSHELL_SESSION_SECRET) alongside this config.
sessionSecret: "${TRIGGERSHELL_SESSION_SECRET}"
sessionTtlHours: 12
users:
- username: admin
passwordHash: ${TRIGGERSHELL_USER_ADMIN_PASSWORD_HASH}
# Add a user with: triggershell users add <username>
tokens:
- name: test-verification
tokenHash: ${TRIGGERSHELL_TOKEN_TEST_VERIFICATION_HASH}
# Add an API token with: triggershell users add-token <name>
database:
path: .triggershell/triggershell.db
logs:
dir: .triggershell/logs
retentionDays: 30
scripts:
- id: openrgb-hue-apply
name: "OpenRGB: Apply Hue Scene"
description: Apply a Philips Hue scene as a static color gradient across OpenRGB-controlled lights (motherboard, GPU, RAM, etc).
command: bash
args:
- -c
- |
# systemd --user units run with a minimal PATH that skips pyenv shims
# and pip's --user bin dir, so add the common locations as a fallback.
export PATH="$HOME/.local/bin:$HOME/.pyenv/shims:$PATH"
if ! command -v openrgb-hue >/dev/null 2>&1; then
echo "error: 'openrgb-hue' was not found on PATH." >&2
echo "Install it with:" >&2
echo " pip install --index-url https://dev.pivoine.art/api/packages/valknar/pypi/simple/ --extra-index-url https://pypi.org/simple openrgb-hue" >&2
exit 1
fi
exec openrgb-hue apply "$SCENE" "$@"
- openrgb-hue-apply
cwd: ./
timeoutSeconds: 30
variables:
- name: scene
label: Scene
description: Philips Hue scene to render as a gradient.
type: enum
required: true
control: combobox
passAs: env
envName: SCENE
choices:
- "Tropical twilight"
- "Blossom"
- "Bright"
- "Savanna sunset"
- "Relax"
- "Energize"
- "Dreamy dusk"
- "Concentrate"
- "Warm embrace"
- "Golden pond"
- "Honolulu"
- "Rest"
- "Ruby glow"
- "Rolling hills"
- "Precious"
- "Cool bright"
- "Mountain breeze"
- "Read"
- "Dimmed"
- "Narcissa"
- "Crocus"
- "Nightlight"
- "São Paulo"
- "Ruby romance"
- "Sunset allure"
- "Smitten"
- "Promise"
- "City of love"
- "Lovebirds"
- "Glitz and glam"
- "Nighttime"
- "Unwind"
- "Shine"
- "Sleepy"
- "Storybook"
- "Arise"
- "Baby's breath"
- "Malibu pink"
- "Rio"
- "Ibiza"
- "Tokyo"
- "Fairfax"
- "Cancun"
- "Chinatown"
- "Osaka"
- "Motown"
- "Galaxy"
- "Blood moon"
- "Moonlight"
- "Starlight"
- "Arctic aurora"
- "Nebula"
- "Ocean dawn"
- "Sunday morning"
- "Spring blossom"
- "Lake mist"
- "Frosty dawn"
- "Emerald isle"
- "Beginnings"
- "Horizon"
- "Sunflare"
- "First light"
- "Valley dawn"
- "Emerald flutter"
- "Memento"
- "Resplendent"
- "Scarlet dream"
- "Amethyst valley"
- "Hazy days"
- "Autumn gold"
- "Winter mountain"
- "Misty ridge"
- "Midsummer sun"
- "Spring lake"
- "Midwinter"
- "Amber bloom"
- "Painted sky"
- "Orange fields"
- "Blue Planet"
- "Lily"
- "Winter beauty"
- "Forest adventure"
- "Meriete"
- "Soho"
- "Magneto"
- "Disturbia"
- "Vapor wave"
- "Tyrell"
- "Hal"
- "Still waters"
- "Pensive"
- "Sundown"
- "Palm Beach"
- "Adrift"
- "Majestic morning"
- "Blue lagoon"
- "Lake Placid"
- "Zandvoort"
- "Miami"
- "Bahrain"
- "Singapore"
- "Silverstone"
- "Suzuka"
- name: mapping
label: Mapping Mode
description: How the gradient is laid out across your LEDs.
type: enum
choices: [sequence, per-device, per-zone, matrix, mirror, shuffle]
default: per-zone
control: select
passAs: arg
argName: --mapping
- name: direction
label: Matrix Direction
description: Only used when mapping is "matrix".
type: enum
choices: [left-right, top-bottom, diagonal, radial]
default: left-right
control: select
passAs: arg
argName: --direction
- name: deviceType
label: Device Type
description: Limit to devices of this type. Leave unset to target every device.
type: enum
required: false
choices: [DRAM, GPU, MOTHERBOARD]
control: select
passAs: arg
argName: --device-type
- name: device
label: Device
description: Limit to a single device by name. Leave unset to target every device.
type: enum
required: false
choices:
- "Corsair Vengeance RGB DDR5"
- "Gigabyte GeForce RTX 3060 Gaming OC"
- "MSI MYSTIC LIGHT"
control: select
passAs: arg
argName: --device
- name: zone
label: Zone
description: Limit to a single zone by name. Leave unset to target every zone.
type: enum
required: false
choices:
- "Corsair DRAM"
- "GPU Zone"
- "JAF"
- "JARGB 1"
- "JARGB 2"
- "JARGB 3"
control: select
passAs: arg
argName: --zone
- name: seed
label: Shuffle Seed
description: Only used when mapping is "shuffle".
type: number
default: 0
passAs: arg
argName: --seed
- name: interpolation
label: Interpolation
description: Color space used to interpolate between gradient stops.
type: enum
choices: [rgb, hsv]
default: hsv
control: select
passAs: arg
argName: --interpolation
- name: dim
label: Dim
description: Global brightness multiplier (0-1), independent of the scene's own brightness.
type: number
default: 1.0
min: 0
max: 1
step: 0.05
control: slider
passAs: arg
argName: --dim
- name: noDedupe
label: Disable Color Deduping
description: Keep consecutive duplicate colors instead of collapsing them into one gradient stop.
type: boolean
default: false
control: switch
passAs: flag
argName: --no-dedupe
- name: noBrightness
label: Ignore Scene Brightness
description: Don't scale each gradient stop by the scene's recorded light brightness.
type: boolean
default: false
control: switch
passAs: flag
argName: --no-brightness
- name: fast
label: Fast Mode
description: Use OpenRGB's no-readback fast update mode.
type: boolean
default: false
control: switch
passAs: flag
argName: --fast
- name: dryRun
label: Dry Run
description: Preview the result without touching real hardware.
type: boolean
default: false
control: switch
passAs: flag
argName: --dry-run
- name: dryRunLeds
label: Dry Run LED Count
description: Number of synthetic flat LEDs to use for Dry Run. Ignored otherwise.
type: number
required: false
min: 1
passAs: arg
argName: --dry-run-leds
- id: openrgb-hue-off
name: "OpenRGB: Turn Off Lights"
description: Turn off OpenRGB-controlled LEDs. Leave every filter unset to turn off all of them.
command: bash
args:
- -c
- |
export PATH="$HOME/.local/bin:$HOME/.pyenv/shims:$PATH"
if ! command -v openrgb-hue >/dev/null 2>&1; then
echo "error: 'openrgb-hue' was not found on PATH." >&2
echo "Install it with:" >&2
echo " pip install --index-url https://dev.pivoine.art/api/packages/valknar/pypi/simple/ --extra-index-url https://pypi.org/simple openrgb-hue" >&2
exit 1
fi
exec openrgb-hue off "$@"
- openrgb-hue-off
cwd: ./
timeoutSeconds: 30
variables:
- name: deviceType
label: Device Type
description: Limit to devices of this type. Leave unset to target every device.
type: enum
required: false
choices: [DRAM, GPU, MOTHERBOARD]
control: select
passAs: arg
argName: --device-type
- name: device
label: Device
description: Limit to a single device by name. Leave unset to target every device.
type: enum
required: false
choices:
- "Corsair Vengeance RGB DDR5"
- "Gigabyte GeForce RTX 3060 Gaming OC"
- "MSI MYSTIC LIGHT"
control: select
passAs: arg
argName: --device
- name: zone
label: Zone
description: Limit to a single zone by name. Leave unset to target every zone.
type: enum
required: false
choices:
- "Corsair DRAM"
- "GPU Zone"
- "JAF"
- "JARGB 1"
- "JARGB 2"
- "JARGB 3"
control: select
passAs: arg
argName: --zone
- id: spotify-start
name: "Spotify: Start App"
description: >-
Launch the Spotify desktop app on the local session. Does nothing if it is
already running (Spotify focuses its existing window).
command: bash
args:
- -c
- |
# triggershell.service starts before the graphical session, so its own
# environment has no WAYLAND_DISPLAY/DISPLAY and a stripped-down PATH.
# systemd-run --user launches Spotify from the user manager instead,
# which does carry the full graphical environment.
if systemctl --user --quiet is-active spotify.service; then
echo "Spotify is already running."
exit 0
fi
systemctl --user reset-failed spotify.service 2>/dev/null || true
exec systemd-run --user --collect --quiet --unit=spotify spotify-launcher
- spotify-start
cwd: ./
timeoutSeconds: 20
variables: []
- id: spotify-stop
name: "Spotify: Stop Playback"
description: >-
Pauses Spotify playback on the local session via its MPRIS D-Bus
interface. Does nothing if Spotify is not running.
command: bash
args:
- -c
- |
# triggershell.service starts before the graphical session and has no
# DBUS_SESSION_BUS_ADDRESS, so point dbus-send at the user bus socket
# directly (systemctl --user works here, so this socket exists).
bus="unix:path=${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/bus"
if ! dbus-send --bus="$bus" --print-reply --dest=org.freedesktop.DBus \
/org/freedesktop/DBus org.freedesktop.DBus.ListNames 2>/dev/null \
| grep -q '"org.mpris.MediaPlayer2.spotify"'; then
echo "Spotify is not running."
exit 0
fi
exec dbus-send --bus="$bus" --print-reply --type=method_call \
--dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 \
org.mpris.MediaPlayer2.Player.Pause
- spotify-stop
cwd: ./
timeoutSeconds: 15
variables: []
- id: system-shutdown
name: "System: Shutdown"
description: >-
Powers off this machine. Type "shutdown" in the Confirm field to proceed.
Optionally schedule it a few minutes out (cancel a pending one with "System: Cancel Shutdown").
command: bash
args:
- -c
- >-
if [ "$CONFIRM" != "shutdown" ]; then
echo 'Aborted: type "shutdown" in the Confirm field to proceed.' >&2; exit 1;
fi;
when=now;
if [ "${DELAY_MINUTES:-0}" -gt 0 ] 2>/dev/null; then when="+$DELAY_MINUTES"; fi;
echo "Scheduling poweroff ($when)...";
exec shutdown -h "$when"
timeoutSeconds: 30
variables:
- name: confirm
label: Confirm
description: Type "shutdown" (exactly) to confirm you want to power off this machine.
type: string
required: true
pattern: "^shutdown$"
passAs: env
envName: CONFIRM
- name: delayMinutes
label: Delay (minutes)
description: Wait this many minutes before powering off. 0 = immediately.
type: number
default: 0
min: 0
max: 120
passAs: env
envName: DELAY_MINUTES
- id: system-reboot
name: "System: Reboot"
description: >-
Reboots this machine. Type "reboot" in the Confirm field to proceed.
Optionally schedule it a few minutes out (cancel a pending one with "System: Cancel Shutdown").
command: bash
args:
- -c
- >-
if [ "$CONFIRM" != "reboot" ]; then
echo 'Aborted: type "reboot" in the Confirm field to proceed.' >&2; exit 1;
fi;
when=now;
if [ "${DELAY_MINUTES:-0}" -gt 0 ] 2>/dev/null; then when="+$DELAY_MINUTES"; fi;
echo "Scheduling reboot ($when)...";
exec shutdown -r "$when"
timeoutSeconds: 30
variables:
- name: confirm
label: Confirm
description: Type "reboot" (exactly) to confirm you want to reboot this machine.
type: string
required: true
pattern: "^reboot$"
passAs: env
envName: CONFIRM
- name: delayMinutes
label: Delay (minutes)
description: Wait this many minutes before rebooting. 0 = immediately.
type: number
default: 0
min: 0
max: 120
passAs: env
envName: DELAY_MINUTES
- id: system-cancel-shutdown
name: "System: Cancel Shutdown"
description: Cancels a pending scheduled shutdown or reboot.
command: shutdown
args: ["-c"]
timeoutSeconds: 15
variables: []