Author SHA1 Message Date
m3ta-chiron 1b61c1cb0c docs(voice-notify): API key from agenix file instead of env var
Prerequisites updated: /run/agenix/elevenlabs-key is now the primary
source, ELEVENLABS_API_KEY env var is the fallback.
2026-07-02 20:10:19 +02:00
m3ta-chiron fc606ace2d docs(skills): add crunch-jobs and update voice-notify
Adds crunch-jobs skill for scheduling voice reminders, AI crunch jobs,
and script-based pipelines via crunch/talk.

Updates voice-notify with stdin piping examples and cancel-button
implementation notes.
2026-07-02 20:05:29 +02:00
m3tam3re 7c3a3c46f0 Merge pull request 'feat(voice-notify): ElevenLabs TTS notification skill' (#5) from feat/voice-notify-skill into master
Reviewed-on: #5
2026-07-02 18:55:52 +02:00
m3ta-chiron b11d18b4b4 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
2026-07-02 18:53:16 +02:00
4 changed files with 298 additions and 1 deletions
+8 -1
View File
@@ -23,20 +23,27 @@ This repository serves as a **personal AI operating system** - a collection of s
│ └── profile.md # Work style, PARA areas, preferences │ └── profile.md # Work style, PARA areas, preferences
├── commands/ # Custom command definitions ├── commands/ # Custom command definitions
│ └── reflection.md │ └── reflection.md
├── skills/ # Opencode Agent Skills (14 skills) ├── skills/ # Opencode Agent Skills (18 skills)
│ ├── agent-development/ # Agent creation and configuration │ ├── agent-development/ # Agent creation and configuration
│ ├── basecamp-project/ # Basecamp project setup & workflows
│ ├── brainstorming/ # Ideation & strategic thinking │ ├── brainstorming/ # Ideation & strategic thinking
│ ├── changelog/ # Changelog generation
│ ├── crunch-jobs/ # Scheduled voice notifications & AI jobs
│ ├── doc-translator/ # Documentation translation │ ├── doc-translator/ # Documentation translation
│ ├── excalidraw/ # Architecture diagrams │ ├── excalidraw/ # Architecture diagrams
│ ├── m3ta-brain/ # Shared brain vault integration
│ ├── mem0-memory/ # DEPRECATED — replaced by opencode-memory plugin │ ├── mem0-memory/ # DEPRECATED — replaced by opencode-memory plugin
│ ├── obsidian/ # Obsidian vault management │ ├── obsidian/ # Obsidian vault management
│ ├── outline/ # Outline wiki integration │ ├── outline/ # Outline wiki integration
│ ├── pdf/ # PDF manipulation toolkit │ ├── pdf/ # PDF manipulation toolkit
│ ├── plan-writing/ # Implementation plan authoring
│ ├── prompt-engineering-patterns/ # Prompt patterns │ ├── prompt-engineering-patterns/ # Prompt patterns
│ ├── qmd/ # Knowledge retrieval via QMD │ ├── qmd/ # Knowledge retrieval via QMD
│ ├── reflection/ # Conversation analysis │ ├── reflection/ # Conversation analysis
│ ├── shared-brain-vault/ # Git-synced Obsidian vault
│ ├── skill-creator/ # Meta-skill for creating skills │ ├── skill-creator/ # Meta-skill for creating skills
│ ├── systematic-debugging/ # Debugging methodology │ ├── systematic-debugging/ # Debugging methodology
│ ├── voice-notify/ # ElevenLabs TTS voice notifications
│ └── xlsx/ # Spreadsheet handling │ └── xlsx/ # Spreadsheet handling
├── scripts/ # Repository utility scripts ├── scripts/ # Repository utility scripts
│ └── test-skill.sh # Test skills without deploying │ └── test-skill.sh # Test skills without deploying
+131
View File
@@ -0,0 +1,131 @@
---
name: crunch-jobs
description: "Use when: (1) The user asks to be reminded at a specific time, (2) Schedule recurring notifications, (3) Set up AI-powered scheduled jobs (summarize, review, report), (4) Run custom pipeline scripts on a schedule with voice output. Triggers: remind me, erinnere mich, schedule, cron, daily, weekly, täglich, jeden Montag, crunch, talk at, notify me at, voice reminder."
compatibility: opencode
---
# crunch-jobs
Schedule voice-notified reminders and AI crunch jobs on NixOS via `systemd` transient timers. When a timer fires, results are spoken aloud through `talk` (ElevenLabs TTS).
No NixOS rebuild needed — jobs are created at runtime via `systemd-run --user` and survive reboots.
## Prerequisites
- `crunch` and `talk` installed (via `m3ta-nixpkgs`)
- `ELEVENLABS_API_KEY` in environment (or agenix secrets)
- `loginctl enable-linger <username>`**critical**: without this, user timers stop when the session ends
**Companion skill:** `voice-notify` covers the `talk` TTS script internals.
## Command Reference
```
crunch at <time> <message> One-shot (14:30 or "2026-07-03 14:30")
crunch in <duration> <message> One-shot after delay (30m, 2h, 1h30m)
crunch daily <time> <message> Recurring daily
crunch weekly <day> <time> <message> Recurring weekly (Mon or Montag)
crunch ai <engine> <type> <time> <prompt> AI crunch (pi|opencode)
crunch script <type> <time> <script.sh> [args] Custom script → talk
crunch list List active jobs
crunch cancel <name> Cancel a job
crunch purge Remove fired one-shot jobs
```
## Decision Flow
### 1. What kind of job?
| User intent | Command |
|---|---|
| "Erinnere mich an X" (just speak a message) | `crunch <type> <time> <message>` |
| "Fasse Y zusammen und sag mir Bescheid" (AI processes data) | `crunch ai <engine> <type> <time> <prompt>` |
| Complex multi-step pipeline (fetch → process → write → speak) | `crunch script <type> <time> <script.sh>` |
### 2. When?
| User says (DE/EN) | Type | Time spec |
|---|---|---|
| "in 30 Minuten" / "in 30m" | `in` | `"30m"` |
| "in 2 Stunden" | `in` | `"2h"` |
| "um 14:30" | `at` | `"14:30"` |
| "morgen um 10:00" | `at` | `"10:00"` (fires next 10:00) |
| "am 3. Juli um 15:00" | `at` | `"2026-07-03 15:00"` |
| "täglich um 9 Uhr" | `daily` | `"09:00"` |
| "jeden Montag um 9" | `weekly` | `"Mon 09:00"` |
| "freitags um 17:00" | `weekly` | `"Fri 17:00"` |
Day names: Mo/Mon/Montag→Mon, Di/Tue→Tue, Mi/Wed→Wed, Do/Thu→Thu, Fr/Fri→Fri, Sa/Sat→Sat, So/Sun→Sun.
### 3. Construct and execute the command.
## Job Types
### Simple Voice Reminders
Just speaks the message at the scheduled time:
```bash
crunch at "14:30" "Müll rausbringen"
crunch in "30m" "Build ist fertig — Ergebnis checken"
crunch daily "09:00" "Guten Morgen! Tagesplanung:"
crunch weekly "Fri 16:00" "Weekly Review nicht vergessen"
```
### AI Crunch Jobs
Runs a prompt through `pi` or `opencode` in print mode (non-interactive). Agent processes data, stdout → `talk`:
```bash
crunch ai pi in "2h" "Lies die neuesten Git-Commits und gib eine 3-Satz Zusammenfassung"
crunch ai opencode daily "07:30" "Check die PostgreSQL-Logs auf Errors der letzten 24h"
crunch ai pi weekly "Mon 09:00" "Generiere Weekly Summary aus git log"
```
The agent has full file-system access. It can call CLI tools, write files, and chain operations. Only the final stdout becomes the voice message.
### Custom Script Jobs
Runs any shell script on schedule. Script stdout → `talk`. Empty stdout = silence (no error).
```bash
crunch script daily "08:00" ~/scripts/basecamp-daily.sh
crunch script weekly "Mon 09:00" ~/scripts/weekly-report.sh arg1 arg2
```
Example script — fetches data, AI summarizes, writes report, speaks summary:
```bash
#!/usr/bin/env bash
# ~/scripts/basecamp-daily.sh
TODOS=$(basecamp todos --today 2>/dev/null) || exit 0
echo "$TODOS" | pi -p "Erstelle strukturierte Summary, speichere als ~/reports/daily.md. Antworte mit Top 3 Prioritäten."
```
## After Scheduling
- crunch outputs `✓ Scheduled: crunch-<name>-<random>`
- Share the job name with the user (needed for cancel)
- List: `crunch list`
- Cancel: `crunch cancel <name>`
## Examples
```
User: "Erinnere mich in 30 Minuten daran, den Build zu checken"
→ crunch in "30m" "Build checken"
User: "Jeden Morgen um 8 will ich meine Basecamp Todos hören"
→ crunch ai pi daily "08:00" "Hole heutige Todos aus Basecamp, antworte mit Top 3 Prioritäten"
User: "Freitags um 16 Uhr will ich ein Weekly Report als Voice"
→ crunch script weekly "Fri 16:00" ~/scripts/weekly-report.sh
```
## Pitfalls
- **Lingering**: Without `loginctl enable-linger <user>`, user systemd timers STOP when the session ends. Verify: `loginctl show-user <username> | grep Linger`
- **No session on servers**: `systemd-run --user` needs an active user session. On headless servers, use system-level timers or Hermes cron instead.
- **Quote messages**: Always quote the message/prompt argument (spaces, special chars).
- **Date format**: Specific dates must be `YYYY-MM-DD` for `crunch at`.
- **Voice toggle**: `VOICE_NOTIFY=0` silences all talk output globally.
+120
View File
@@ -0,0 +1,120 @@
---
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 at `/run/agenix/elevenlabs-key` (preferred) or `ELEVENLABS_API_KEY` env var (fallback)
- 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."
```
### Stdin (Pipe)
```bash
echo "Deployment fertig" | talk
nixos-rebuild build 2>&1 | tail -3 | talk
# AI agent print mode → talk
pi -p "Review diesen Code" | talk
opencode run "Erkläre diese Funktion" -q | talk
```
Argument has priority; if no argument is given, `talk` reads from stdin. This enables piping from any command or AI agent.
### 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 `/run/agenix/elevenlabs-key` exists and is readable (or `ELEVENLABS_API_KEY` env var). HTTP 402 = no credits
- **No popup?** Ensure a notification daemon is running (`notify-send` needs a daemon)
- **Cancel button doesn't stop audio?** Fixed: the poll loop now uses `[ -s ]` (non-empty check) instead of `[ -f ]` (exists). The action file is created as empty by the shell redirect; it's only filled when the user clicks Abbrechen.
- **`pw-play` doesn't work** — it can't decode MP3; `talk` uses `mpv` which handles all formats
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# cruncher-notify.sh — Wrapper für Jobs mit Voice Notification
# Usage: cruncher-notify.sh "Job Name" -- <command...>
# 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\" -- <command...>"; 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"