All plugins

leitmotif

Hear what your agent is doing. Every tool call becomes a short musical motif from a pure-Python synth, so reads, writes, shell commands, loops (the motif repeats and climbs), error streaks (dissonant, sinking), pending approvals (a heartbeat, then a distinct still-waiting cue until you answer) and finished turns (a V-I cadence) are audible without watching the screen; also a non-visual status channel for blind and low-vision developers. Modes full / ambient / alerts-only, themes studio / arcade / zen, and /leitmotif export saves a session as WAV, MIDI and a piano-roll SVG. Disclosure — observer-only hooks, never blocks or approves anything; starts the OS audio player (afplay, pw-play, paplay or aplay) as a short-lived subprocess per sound, or uses winsound on Windows; keeps tool names and argument hashes in memory only; caches rendered notes and writes exports in its plugin data directory; no network calls, no telemetry, no credentials.

JustSteezVoicev0.1.1Updated 29 minutes ago

About

Hear what your agent is doing. Every tool call becomes a short musical motif from a pure-Python synth, so reads, writes, shell commands, loops (the motif repeats and climbs), error streaks (dissonant, sinking), pending approvals (a heartbeat, then a distinct still-waiting cue until you answer) and finished turns (a V-I cadence) are audible without watching the screen; also a non-visual status channel for blind and low-vision developers. Modes full / ambient / alerts-only, themes studio / arcade / zen, and /leitmotif export saves a session as WAV, MIDI and a piano-roll SVG. Disclosure — observer-only hooks, never blocks or approves anything; starts the OS audio player (afplay, pw-play, paplay or aplay) as a short-lived subprocess per sound, or uses winsound on Windows; keeps tool names and argument hashes in memory only; caches rendered notes and writes exports in its plugin data directory; no network calls, no telemetry, no credentials.

🎼 Leitmotif

Hear what your agent is doing.

Leitmotif turns every Hermes tool call into a short musical motif, generated live by a tiny pure-Python synthesizer. You don't have to watch the terminal to know what's happening:

  • Reading sounds like high plucked strings, writing like a warm pad swell, and shell commands like marimba.
  • A loop is audible. The same call always plays the same motif, so when the agent retries npm test for the fifth time, the motif repeats and climbs, with a tritone warning from the third time on.
  • Errors clash. Consecutive failures sink lower, and a recovery resolves upward.
  • Waiting on you sounds like a heartbeat. It keeps pulsing until you answer the approval prompt, then confirms with a bright third (approved) or a low thump (denied). If you're away for more than 5 minutes, the heartbeat gives way to a distinct still waiting cue and a soft reminder every minute, so a pending approval never sounds like an idle agent.
  • Turns resolve. A finished turn ends on a V → I cadence; a failed or interrupted one doesn't resolve.

Long-running agents are meant to be left alone, and Leitmotif is how you keep half an ear on one. It's also a non-visual status channel for blind and low-vision developers. No screen reader has to announce every tool call, because the music carries it.

piano roll of a session

A real session, exported with /leitmotif export. Reads up high, a write, a failing npm test loop (orange staircase) over sinking errors (red), the fix, three approval heartbeats (white), and the closing cadence. Listen to it.

Commands

/leitmotif                status
/leitmotif tour           play every cue once, with what it means
/leitmotif legend         which sound means what
/leitmotif on | off       unmute / mute (the session keeps recording)
/leitmotif mode <full|ambient|alerts>
/leitmotif theme <studio|arcade|zen>
/leitmotif volume <0-100>
/leitmotif export [name]  save the session as WAV + MIDI + piano-roll SVG
  • full: every tool call
  • ambient: every tool call, at half volume
  • alerts: silent until something needs you: an approval, an error streak, a loop, a subagent failing, or a turn ending

What you're hearing

| event | sound |
|---|---|
| shell commands | marimba, mid register |
| reading / searching | high plucked strings |
| writing / patching files | warm low pad swell |
| web / browser | FM bell |
| subagents | glass voice rises when one starts, settles when it ends |
| tool error | dissonant minor-second buzz, lower with each consecutive error |
| identical call repeated | same motif, a semitone higher each time; tritone warning from the 3rd |
| waiting for your approval | heartbeat until you answer (up to 5 min) |
| still waiting (heartbeat cap reached) | one low beat under a rising, unresolved question; then a soft reminder every minute until you answer |
| approved / denied | bright major third / low falling thump |
| turn finished | V → I cadence |
| turn interrupted / failed | falling fourth / minor iv → i |

Each session gets its own key (derived from the session id), so two agents running side by side sound different.

Install

hermes plugins install JustSteez/hermes-leitmotif
hermes plugins enable leitmotif

Then start a session and run /leitmotif tour.

Configuration

| key | default | |
|---|---|---|
| enabled | true | play sounds (recording continues when muted) |
| mode | full | full, ambient, or alerts |
| theme | studio | studio, arcade (chiptune), or zen (glass and pads) |
| volume | 60 | 0–100 |
| loop_threshold | 2 | identical calls per task before the motif starts climbing |
| heartbeat_max_seconds | 300 | how long the approval heartbeat runs before the still waiting cue |
| approval_reminder_seconds | 60 | after that, how often the soft reminder plays until you answer (0 = off) |
| max_events_per_sec | 6 | ambient sounds above this rate are skipped; alerts always play |
| player | auto | afplay (macOS), pw-play / paplay / aplay (Linux), winsound (Windows), or none |
| finalize_notice | true | offer /leitmotif export when a session with 30+ notes closes |

How it works

  • Hooks only, observer only. It listens on pre_tool_call, post_tool_call, pre_approval_request, post_approval_response, subagent_start, subagent_stop, on_session_start, on_session_end and on_session_finalize. It never blocks, modifies or approves anything.
  • Never stalls the agent. Hooks only push notes onto a queue. One daemon thread renders and plays them. Every hook catches its own errors.
  • Pure-Python synth. Additive marimba and glass, Karplus–Strong plucked strings, a 2-operator FM bell, detuned pads and chiptune squares. There are no dependencies, no numpy and no audio libraries. Each note renders in a few milliseconds and is cached to disk, so a repeated motif costs nothing.
  • Plays through the OS player. It uses afplay, pw-play, paplay, aplay or winsound. On a headless gateway with no audio device it stays silent and just records.
  • Export. Long idle gaps (the model thinking) are squeezed out, so a session exports as a listenable piece. The MIDI file uses one General MIDI channel per instrument, with marker events naming each cue.

Privacy and risk disclosures

  • No network calls, no telemetry, no credentials.
  • It starts the OS audio player (afplay, pw-play, paplay or aplay) as a short-lived subprocess for each sound. It runs no other commands.
  • It keeps tool names and a hash of each call's arguments in memory to build motifs. Arguments themselves are never written to disk.
  • It writes rendered note WAVs to its plugin data directory as a cache, and writes exports only when you run /leitmotif export.

Tests

python3 -m unittest discover -s tests

License

MIT

README from the reviewed commit 7d22129; it updates when the author re-pins.

Developer Mode

Explore built-in Hermes toolsets and actions.

HermesAgent

Developer?

Create a Hermes extension for Desktop or agent workflows.

Developer Section