From b11d18b4b4dee386d06a4b82f4b4714b8ce7a645 Mon Sep 17 00:00:00 2001 From: m3ta-chiron Date: Thu, 2 Jul 2026 18:53:16 +0200 Subject: [PATCH] feat(voice-notify): add ElevenLabs TTS voice notification skill - SKILL.md with integration patterns (cruncher jobs, agent hooks, post-build) - scripts/cruncher-notify.sh wrapper for long-running jobs - Voice toggle via VOICE_NOTIFY env var --- skills/voice-notify/SKILL.md | 107 ++++++++++++++++++ .../voice-notify/scripts/cruncher-notify.sh | 39 +++++++ 2 files changed, 146 insertions(+) create mode 100644 skills/voice-notify/SKILL.md create mode 100644 skills/voice-notify/scripts/cruncher-notify.sh diff --git a/skills/voice-notify/SKILL.md b/skills/voice-notify/SKILL.md new file mode 100644 index 0000000..a6dd6a4 --- /dev/null +++ b/skills/voice-notify/SKILL.md @@ -0,0 +1,107 @@ +--- +name: voice-notify +description: "Use when: (1) A long-running task (build, test, migration, cruncher job) completes, (2) The user asks to be notified audibly, (3) An agent finishes delegated work and should announce results, (4) Important errors or completions need immediate attention. Triggers: talk, voice, notify, audio, abbrechen, notify me, let me know when done, cruncher, job complete." +compatibility: opencode +--- + +# voice-notify + +ElevenLabs TTS voice notifications with a dismissable desktop popup. Audio playback and notification appear simultaneously — click **⛔ Abbrechen** to stop playback. + +## Prerequisites + +- `talk` binary installed (via `m3ta-nixpkgs pkgs.talk`) +- `ELEVENLABS_API_KEY` set in environment +- Desktop notification daemon (DMS, dunst, mako, etc.) +- Audio playback (`mpv`) and PipeWire/PulseAudio running + +## When to Use + +- **Task completed** — after builds, tests, migrations, deployments (>30s runtime) +- **Cruncher job finished** — long data processing pipelines +- **Agent delegated work done** — when a subagent finishes and the user should know +- **User requested audio feedback** — "notify me when done", "let me know" +- **Critical errors** — build failures, test crashes, missing dependencies + +## When NOT to Use + +- Quick responses (< 30s of work) +- `VOICE_NOTIFY=0` is set — respect the toggle, stay silent +- Headless server without audio/desktop +- User is in a meeting/streaming — audio would be disruptive + +## Usage + +### Basic + +```bash +talk "Build abgeschlossen. Alle 247 Tests erfolgreich." +``` + +### After Task Completion + +```bash +# Am Ende eines langen Jobs: +talk "Cruncher Job komplett. 3 Dateien verarbeitet, 0 Fehler." +``` + +### Disable Temporarily + +```bash +export VOICE_NOTIFY=0 # stumm schalten +# ... agent work ... +export VOICE_NOTIFY=1 # wieder an +``` + +## Integration Patterns + +### Pattern 1: Cruncher Job Wrapper + +For any long-running job, use the wrapper script at `scripts/cruncher-notify.sh`: + +```bash +# Statt direkt: +python3 process_data.py --input data.csv + +# Mit Voice Notification: +cruncher-notify.sh "Data Import" -- python3 process_data.py --input data.csv +# → 🔊 "Data Import erfolgreich. Dauer: 3 Minuten 42 Sekunden." +``` + +On failure: `❌ "Data Import fehlgeschlagen, Code 1"`. + +### Pattern 2: Agent Hook + +Add to `AGENTS.md` in any project: + +```markdown +## Voice Notifications +When `VOICE_NOTIFY != 0` and the task took longer than 30 seconds, +call at the end: `talk "[brief summary]"` +``` + +### Pattern 3: Post-Build / Post-Test + +```bash +# Makefile oder CI script: +test: + pytest tests/ + talk "Tests durchgelaufen: $$(pytest tests/ -q --tb=no 2>&1 | tail -1)" +``` + +## Toggle Behaviour + +| Value | Effect | +|-------|--------| +| `VOICE_NOTIFY=1` (default) | Notifications active | +| `VOICE_NOTIFY=0` | `talk` exits immediately, no audio, no popup | +| unset | Defaults to enabled | + +Set per-shell, per-user, or system-wide via Home-Manager `home.sessionVariables`. + +## Pitfalls + +- **No audio?** Check `ELEVENLABS_API_KEY` is set and has credits (HTTP 402 = no credits) +- **No popup?** Ensure a notification daemon is running (`notify-send` needs a daemon) +- **Popup stays after audio?** The poll-loop should close it; if not, DMS may handle actions differently +- **`pw-play` doesn't work** — it can't decode MP3; `talk` uses `mpv` which handles all formats diff --git a/skills/voice-notify/scripts/cruncher-notify.sh b/skills/voice-notify/scripts/cruncher-notify.sh new file mode 100644 index 0000000..584e02f --- /dev/null +++ b/skills/voice-notify/scripts/cruncher-notify.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# cruncher-notify.sh — Wrapper für Jobs mit Voice Notification +# Usage: cruncher-notify.sh "Job Name" -- +# Example: cruncher-notify.sh "Data Import" -- python3 import.py --input data.csv +set -euo pipefail + +JOB_NAME="$1" +shift +[ "$1" = "--" ] && shift || { echo "Usage: $0 \"Job Name\" -- "; exit 1; } + +START_TS=$(date +%s) + +echo "▶ $JOB_NAME gestartet: $(date +%H:%M:%S)" + +set +e +"$@" +JOB_EXIT=$? +set -e + +END_TS=$(date +%s) +DURATION=$(( END_TS - START_TS )) +MIN=$(( DURATION / 60 )) +SEC=$(( DURATION % 60 )) + +if [ "$JOB_EXIT" -eq 0 ]; then + STATUS_TEXT="erfolgreich" + STATUS_ICON="✅" +else + STATUS_TEXT="fehlgeschlagen (Code $JOB_EXIT)" + STATUS_ICON="❌" +fi + +echo "$STATUS_ICON $JOB_NAME $STATUS_TEXT in ${MIN}m${SEC}s" + +if [ "${VOICE_NOTIFY:-1}" != "0" ] && command -v talk &>/dev/null; then + talk "$JOB_NAME $STATUS_TEXT. Dauer: $MIN Minuten $SEC Sekunden." +fi + +exit "$JOB_EXIT" -- 2.55.0