Skip to main content

heartbeat2

❖ Communityv0.1.1

Wakes and watchers for Hermes agents, maintained by Electric Sheep. You (with /pulse) or your agent (with the pulse tool) arm follow-ups at a time, recurring checks, a check-in after a long silence, or deterministic watchers on a file, process, URL, read-only command or Hermes event (kanban, subagent, API error, reactions). A wake is a turn in the same messaging DM that armed it, on that chat's own model: no side model, cron session or subagent. Watchers decide without a model call; the agent answers each wake with a structured verdict (notify or stay silent, never a typed sentinel); a no-op governor slows, then pauses pointless wakes and asks once. Every guardrail is a user setting (quiet hours, daily caps, unanswered mute, floors, lifetimes) that the agent works inside and can never widen. v0.1 delivers to messaging-gateway DMs only and needs plugins.entries.heartbeat2.allow_gateway_injection: true.

Open in Hermes Desktop
hermes plugins install heartbeat2

What it adds

Tools 1

pulse

Hooks 14

pre_gateway_dispatchgateway_platform_eventpre_llm_callpre_api_requestpost_api_requesttransform_llm_outputon_session_endagent_loop_stoppedon_session_resetkanban_task_completedkanban_task_blockedon_kanban_worker_exitedsubagent_stopapi_request_error

README

From the reviewed commit 50ee8c6 ↗; it updates when the author re-pins.

HeartBeat 2.0

Your Hermes agent can say "I'll check back at four", and then actually do it: in the same chat, on the same model, with everything it already knows. It can watch a build, a log file, a process or a URL and speak up only when something changed. When there is nothing worth saying, it stays quiet.

  • You or your agent create the wakes and watchers. A follow-up at a set time, a recurring check, a check-in after a long silence, or a deterministic watcher on a file, process, URL, read-only command or Hermes event. You arm them with /pulse; the agent arms them with its pulse tool.
  • Same conversation, same model. A wake is a turn in the chat that armed it, on that chat's own model. There is no side model, separate cron session or subagent.
  • It catches its own pointless wakes. A watcher costs no model call until something changes. A wake that keeps finding nothing slows down, suggests a watcher, then pauses and asks you once.
  • You own every guardrail. Quiet hours, daily caps, the unanswered mute, intervals and lifetimes are plugin settings. The agent works inside them: it can only narrow its own wakes (shorter lifetime, fewer fires, slower pacing) or switch itself off, never widen a setting.

What it feels like

A follow-up that reads the room.

You: Remind me at 4 to send the Acme invoice. Agent: Will do. I'll check in at 16:00.

16:00. Agent: It's 4. Did the Acme invoice go out? I can draft the email if that helps.

The wake runs inside your conversation. If you had written "sent it" at 15:10, the 16:00 turn would see that and stay silent. If the agent armed it with "cancel when I reply", any message from you cancels it outright.

A watcher that speaks only when something changed.

You: Keep an eye on the nightly build and tell me if it breaks. Agent: Watching the latest nightly run with a read-only gh run list check every 10 minutes. I'll only look when the result changes, and only message you if it failed.

02:10, after 14 unchanged checks that cost no model turns: Agent: The nightly build failed in tests/test_api.py (3 failures, all timeouts). Want me to dig in this morning?

During quiet hours that message waits until they end, unless you marked the watcher urgent and allowed urgent wakes through.

A pointless wake that catches itself. Say the agent set up an hourly "check the inbox" wake. After three empty checks it starts stretching the interval, and after six it pauses itself. The next time you talk:

Agent: I paused "check the inbox": six checks in a row found nothing. Keep, slow, stop, or turn it into a watcher? (/pulse keep|slow|stop|watch w_3f2a)

A check-in after a long silence (off by default). When it is on, the agent checks in once after a silence (24 h by default) and says how to turn check-ins off. It doesn't check in again until you've talked.

Why "2.0"

Heartbeats, as OpenClaw popularised them, made agents feel alive. They also produced a well-documented list of failures. We turned each one into a deterministic scenario in the benchmark suite:

Heartbeat-1.0 failure HeartBeat 2.0
Stops silently after compaction, sleep or restart The schedule and claims live in SQLite on wall-clock time. After a restart or sleep, missed fires collapse into one.
Duplicate or replayed deliveries Each fire is a durable compare-and-set claim. Only one wake can be in flight per chat, and a wake is never injected into a busy chat.
Message floods (one loop resent 189×) Daily caps on model turns and messages, spacing between wakes, a mute after unanswered messages, and an error ladder that ends in a pause.
"HEARTBEAT_OK" leaking into the chat The model never types a sentinel. It calls pulse respond notify=false, and the plugin makes the turn silent.
Messages to the wrong chat or person There is no destination parameter at all. A wake can only return to the chat that armed it, and only in DMs by default.
Most spend going to no-op ticks Watchers decide without a model call. The no-op governor backs off, then pauses.

Totals over 23 deterministic scenarios (B1 simulation driving the real engine; python -m bench.run --baseline --gate, source 77f0bd4). The comparison arm is a naive heartbeat-1.0 emulator built from documented failure reports. It is not a measurement of OpenClaw itself.

Across the suite HeartBeat 2.0 Naive heartbeat
Duplicate deliveries 0 1
Required fires missed 0 9
Sentinel text leaked into chat 0 2
Messages to the wrong chat 0 2
Most messages in one minute 1 100
Model turns 42 504
Model turns that found nothing 15 78
Estimated input tokens 6,300,000 75,600,000

Every scenario and its hard bars are in bench/README.md; the full per-scenario table is regenerated per commit.

How it works

  you (/pulse) or the agent (pulse tool): what, when or what to watch, bounds
                                   │
                    durable schedule (SQLite in the profile)
                                   │
        time · silence · file · process · URL · command · Hermes event
                                   │
              nothing changed? ──► no model call, nothing sent
                                   │ due / changed / deadline
     gates: enabled · estop · paused · provider health · quiet hours ·
            unanswered mute · daily caps · busy · spacing · one in flight
                                   │
           one turn in the same chat, on the chat's own model
                                   │
                 pulse respond {outcome, notify, summary}
           notify=false ──► silent          notify=true ──► one short message
                                   │
          ledger + no-op governor (slow down → suggest a watcher → pause → ask once)

One poller per profile runs inside the messaging gateway and ticks every 5 seconds. A file lock guarantees only one poller even when several Hermes processes share the profile. Every fire is a durable claim with an attempt marker. An accepted turn that never starts is tried three times, and a refused injection backs off and is tried five times, before it is marked dead. A turn that started but never finished (a crash or restart) is recorded as interrupted and never re-run, so you never get the same message twice.

Install

Requires Hermes ≥ 0.21.6 and Python ≥ 3.11 on macOS or Linux. v0.1 delivers into messaging-gateway DMs: Telegram, Discord, Slack, WhatsApp and the other gateway platforms.

hermes plugins install electricsheephq/heartbeat2 --enable

Then allow the plugin to start turns in your conversations. This is a Hermes core key, deliberately kept outside the plugin's own settings:

plugins:
  entries:
    heartbeat2:
      allow_gateway_injection: true

Restart the messaging gateway and send /pulse in your DM. It shows:

  • whether the scheduler is running;
  • whether injection is allowed, with the exact YAML if it isn't;
  • your local time and quiet hours;
  • today's wakes, messages and estimated tokens.

All other settings are in Settings ▸ Plugins in Hermes Desktop or in config.yaml.

Using it

You, in the chat:

Command What it does
/pulse Status: scheduler, consent, local time, quiet hours, today's counts, next due
/pulse add in 2h check the deploy A one-off wake
/pulse add every 1d at 09:00 plan my day A recurring wake at a fixed time
/pulse add when silent 24h ask how the trip went Once per silence of that length
/pulse list · /pulse why <id> Everything armed in this chat; one item's note, reason, status and governor streaks
/pulse ledger [7d] Totals over the range: fires, checks, model turns, messages, replies and estimated tokens
/pulse pause <id|all> [for 3d] · resume · cancel Control one item or all of them
/pulse quiet 22:00-07:30 · quiet for 3h · quiet off · quiet default Quiet hours for this chat; default goes back to your settings
/pulse ok <id> Approve a wake the agent proposed (when Agent can arm wakes is ask_first)
/pulse keep|slow|stop|watch <id> Answer the governor's card for a paused wake (watch pauses it and asks your agent to turn it into a watcher)
/pulse off · /pulse on Turn wakes off or back on for this chat. Only you can turn them back on.

/pulse is a control panel, not conversation. Using it never counts as replying to the agent.

Your agent gets one tool, pulse (create · list · update · pause · resume · cancel · respond · off), and the bundled heartbeat2-usage skill. The skill teaches it to:

  • arm a wake only for a named open loop, never just to stay in touch;
  • prefer a watcher to a timer whenever a deterministic check can tell "changed";
  • answer every wake with respond: outcome (no_change · progress · done · blocked · needs_attention), notify, a one-line summary, and optionally next_check and scratch notes for its next wake.

Watchers available to the agent:

Watcher Fires when
file The file changes, or an appended line matches a pattern
process A process exits (PID reuse is detected)
url A GET response changes, or a pattern appears (10 s hard deadline, 256 KB cap)
command A read-only allowlisted command's output changes, it succeeds or fails, or it prints {"fire": true, …}
Hermes events A kanban task completes or blocks, a worker exits, a subagent finishes, the API errors, or someone reacts to or edits a message

Hermes events are selected by trigger.kind: kanban_completed, kanban_blocked, kanban_worker_exited, subagent_done, api_error, reaction (with an optional emojis filter) and message_edited.

Any watcher can carry a deadline, so "nothing happened by Friday" fires once, too.

Settings

These live under plugins.entries.heartbeat2.settings and appear in Settings ▸ Plugins. The agent's tool can't change them. When a request goes past a bound, the tool tells the agent exactly what it clamped.

Setting Key Default What it does
Enabled enabled on Master switch for wakes and watchers in this profile.
Agent can arm wakes agent_can_create yes yes · ask_first (the agent's wakes wait for /pulse ok <id>) · no
Direct messages only dm_only on Refuse group chats. Unknown chat types are refused too.
Time zone timezone (blank) IANA name such as Europe/Paris. Blank uses the profile's time zone.
Quiet hours quiet_hours 22:00-08:00 HH:MM-HH:MM, may cross midnight; blank for none. Due one-shots wait until the end; recurring ticks inside are skipped.
Urgent wakes ignore quiet hours quiet_hours_urgent off Let wakes marked urgent through quiet hours.
Wake turns per day max_model_wakes_per_day 24 Per chat, local day. Each wake turn is a full model turn.
Unprompted messages per day max_messages_per_day 6 Per chat, local day.
Unanswered messages before mute max_unanswered 2 After this many unprompted messages with no reply, the agent's wakes and check-ins pause until you write. Wakes you armed still fire.
Shortest repeat (minutes) min_interval_minutes 15 Floor for every recurring time wake.
Shortest agent timer without a watcher (minutes) agent_ungated_floor_minutes 60 Floor for recurring timers the agent arms without a watcher.
Minutes between wake turns wake_spacing_minutes 10 Per chat.
Fastest watcher check (seconds) probe_floor_seconds 60 Watchers never check more often than this.
Active wakes per chat max_active 10 Also capped at 50 across the profile.
Longest lifetime (days) max_lifetime_days 14 Every wake expires by then; agent recurring wakes default to 7 days.
Check in after a long silence owner_silent_checkin off Off by default. One check-in per silence, with how to turn it off.
Silence before a check-in (hours) checkin_after_hours 24 Doubles for the next silence if a check-in is ignored.
Wake-from-wake depth max_rearm_chain 2 How many wakes deep a chain armed inside wake turns may go; a message from you resets it.
Empty fires before slowing down noop_slowdown_after 3 A recurring wake that keeps finding nothing doubles its interval after this many.
Slow-down multiplier noop_backoff_factor 2 How much each slow-down stretches the interval.
Longest slowed interval (hours) noop_max_backoff_hours 24 Slowing down stops at this interval.
Empty fires before suggesting a watcher suggest_gate_after 4 The wake text suggests turning the timer into a watcher.
Empty fires before pausing noop_pause_after 6 Pauses the wake and asks you once: keep, slow, stop or watch.
Ignored messages before pausing ignored_pause_after 3 Delivered messages with no reply in the engagement window.
Errors in a row before pausing error_pause_after 5 Errors in a row before pausing.
Reply window (hours) engagement_window_hours 6 A reply within this window counts a delivered message as useful.
Catch-up window (hours) catch_up_hours 6 A one-shot more than this late after downtime is reported as missed instead of firing.
Allowed watcher commands probe_commands gh pr view, gh pr checks, gh run view, gh run list, git ls-remote, git status, git log Comma-separated argv prefixes for command watchers. Blank disables command watchers.
Silence check-ins source_silence on Silence check-ins.
Process watchers source_process on Process watchers.
File watchers source_file on File watchers.
URL watchers source_url on URL watchers.
Let URL watchers reach private and local addresses url_allow_private off Allow private and local URL targets (loopback, private ranges). Cloud metadata and the whole IPv4 link-local range 169.254.0.0/16 stay blocked, as Hermes treats that range as metadata.
Command watchers source_command on Command watchers.
Hermes event watchers source_events on Kanban, subagent, API error and reaction events.
Tell the agent what's armed presence_line on One short context line on your turns while something is armed.
Ledger history (days) ledger_days 30 Ledger history (days).

Guardrails, briefly

Every guardrail is configurable:

  • Recurring timers repeat at most every 15 minutes, or every 60 minutes when the agent arms one without a watcher. Watchers check at most once a minute.
  • Every wake expires after 14 days at most.
  • Each chat gets at most 24 wake turns and 6 unprompted messages a day.
  • After 2 unanswered messages, the agent's own wakes and check-ins pause until you write. Wakes you armed still fire.
  • A wake turn that carries untrusted data, such as a log line or a web page, cannot arm new recurring work.
  • Hermes' emergency stop halts every wake.
  • /pulse off stops everything in that chat, and only you can turn it back on.

Cost

A wake turn is an ordinary model turn in that conversation. It is billed like a message, and its size is your conversation's context size: on a long-running agent that can be 100–200k input tokens per wake. Watchers, gates and skipped wakes cost nothing. /pulse status and /pulse ledger show the running count of wake turns and estimated tokens. Start with watchers and long intervals.

Security and privacy

Disclosure — wakes and watchers run full turns on the conversation's own model, billed like any message; command watchers run allowlisted read-only commands without an approval prompt; URL watchers make the GET requests you configured; state stays in the profile's plugin-data; no telemetry. Command environments use Hermes' sanitizer on an allowlisted base and carry no provider, bot or GitHub tokens; gh uses its own hosts.yml or keyring. URL watchers always block cloud metadata, and block private/local addresses unless url_allow_private is enabled, checking every hop at connect time. File watchers honor Hermes read blocks at arm/update and every check, including rotation. Helpers run in the watcher's profile scope.

Command watchers:

  • run only argv prefixes from your allowlist. The default is gh pr view/checks, gh run view/list, git ls-remote/status/log;
  • run with no shell and no terminal;
  • refuse output, config, editor, browser and mutating flags and verbs, including gh --jq/-q and --template/-t;
  • have the whole process group killed after 30 seconds.

The argv guard is not a sandbox: only allow programs you trust to be read-only. URL watchers refuse credentials in the URL and send no cookies, auth headers or proxy settings. Wake turns keep the conversation's normal tools and permissions. Full threat model and limits: SECURITY.md.

The default command allowlist still permits gh -R HOST/... and git ls-remote <url> to reach any host the machine can reach; v0.1.1 does not change this exception.

Roadmap

Compatibility and known issues

  • v0.1 delivers only to messaging-gateway DMs. It refuses to arm wakes from the CLI, TUI, Desktop, the API server or cron: a CLI wake would interrupt your turn, and TUI/Desktop have no silence filter for injected turns yet. Desktop and TUI wakes are planned for v0.2, once Hermes core supports them.
  • A wake turn that fails at the provider (quota, auth, outage) shows Hermes's own failure notice in the chat. The plugin cannot suppress it (NousResearch/hermes-agent#136749). HeartBeat 2.0 settles that wake, then holds every wake back (5 min → 15 min → 1 h → 4 h) until a model call on the profile succeeds again. A long outage therefore costs one notice per backoff step, not one per wake.
  • Silence covers the final reply. notify=false keeps the agent's reply out of the chat. On platforms that show tool progress by default (Discord; WhatsApp and Matrix show new tools), each wake turn still posts a progress bubble. Telegram and Slack hide tool progress by default. To keep wakes fully silent there, set display.platforms.<platform>.tool_progress: off. A quiet-injection option is requested upstream (NousResearch/hermes-agent#136825).
  • Messages sent while the agent is busy. On Signal/SimpleX, a message that waits in Hermes' queue while a turn is running (a photo, or any message when busy_input_mode is queue) reaches the agent without a message id, so HeartBeat 2.0 does not count it as your reply. The unanswered mute and the silence check-in treat you as silent until your next message. Text you send mid-turn in the default mode is counted. With the Codex app-server runtime, its native steer (text you send into a running wake turn) is not detected, so a wake that decides to stay silent can leave that steer unanswered.
  • Memory providers see wake text as a user turn (NousResearch/hermes-agent#130622). An external memory provider may store a wake's instructions as if you had written them.
  • Kanban watchers only see tasks whose worker runs in this profile. A task assigned to another profile completes in that profile's worker, out of sight.
  • codex_app_server turns drop per-turn context, so the presence line and governor card don't reach the model on that provider path. Wakes still fire, and silence still works.
  • File watchers poll. A truncate-and-regrow or a replacement that happens entirely between two checks can be missed. Reading catches up within 4 MB per check, and lines over 256 KB are skipped.
  • Notes, scratch, summaries and event payloads are stored in plaintext in <profile>/plugin-data/heartbeat2/pulse.db. Don't watch credential files.
  • Live proof so far: one profile (Telegram DM, GLM model) covered a delivered follow-up, a silent verdict and survival across a gateway restart. The benchmark suite is a deterministic simulation of the engine, not a measurement of live delivery.

How it compares

A workflow comparison, not a measured parity claim.

Option What it is When to pick it instead
HeartBeat 2.0 Wakes and watchers that you or the agent create. They run in the live DM on its own model, with deterministic watchers, owner-set bounds, structured silence and a no-op governor.
Hermes /heartbeat (core) One recurring instruction for the current session, with core persistence and idle admission. Silence is a bare marker. You want one periodic nudge and nothing else.
Hermes /loop Repeats an instruction in the active interactive session. You are working at the keyboard, not waiting on something.
Hermes cron Scheduled jobs, each in a fresh session with no conversation history, delivering a report. A no_agent job's script can print {"wakeAgent": false} to stay silent. HeartBeat 2.0 borrows that idea for command watchers but fires inside the live conversation. Independent scheduled tasks that don't need the conversation.
hermes-cron An operating skill and doctor for core cron. Complementary: it makes cron easier, it isn't a scheduler.
jev-cron-gate A pre-run gate for core cron: a side model answers yes or no on whether a run is pointless, then the run happens in a fresh cron session. HeartBeat 2.0's gates are deterministic, with no side model. You already run cron jobs and want to skip pointless ones.
Alan's Way An idle check-in for one bound Telegram DM after 2 h of quiet (08:00–22:00), which may take one safe step, bundled with a desktop workspace app and services. It uses the same injection seam. You want that whole workspace and a single fixed check-in rhythm.
OpenClaw heartbeat A periodic heartbeat inside the main conversation. HeartBeat 2.0 was designed against its documented failure reports; it is not a port, and it makes no claim about OpenClaw's current behaviour. You run OpenClaw.

Development

python -m pytest -q                                   # unit tests (network denied)
HERMES_HOME=$(mktemp -d) HERMES_DISABLE_LAZY_INSTALLS=1 HEARTBEAT2_REQUIRE_HERMES=1 \
  PYTHONPATH=/path/to/hermes-agent python -m pytest tests/integration -q   # real Hermes loader
python -m bench.run --baseline --gate --out bench-out  # simulation benchmark + gate

CI runs the unit tests on Ubuntu and macOS with Python 3.11, 3.13 and 3.14. It also runs the real-loader integration test against Hermes v0.21.6 and a pinned main commit. A mutant test applies known-bad changes to a temporary copy of the engine (replayed slots, claim CAS off, flock off, estop off, raw transform, cancel-on-reply off and more), and checks that the benchmark gate fails for each one. That keeps the gate from becoming a tautology.

Credits: claim, refund and coalescing semantics follow Hermes core /heartbeat. Fingerprinting follows Hermes' cron monitor, and estop and busy ordering follow the gateway. OpenClaw's public issue reports shaped the benchmark scenarios.

Built for Hermes Agent by Electric Sheep. Apache-2.0.

boardstate❖ Community★ 4

A live board the agent builds for you: a Board tab in the Hermes dashboard and a Desktop page where the agent lays out tabs and widgets (notes, markdown, tables, charts, KPI cards, live Hermes data, approvals) through 19 native boardstate_* tools. Runs a local Node >= 20 sidecar on loopback with a per-spawn nonce; no network access unless you opt in to operator-gated connectors. Disclosure — spawns a local Node.js ≥20 sidecar (from PATH/HERMES_NODE_BIN, nothing downloaded) on 127.0.0.1 on first use; state under HERMES_HOME/boardstate-state/. Reads the dashboard's loopback session token from Hermes internals (web_server._SESSION_TOKEN) and passes it to the sidecar for live usage/sessions/cron widgets; mounts one token-gated static route for approved widget assets. No outbound network unless you author boardstate.connectors.json (stdio/HTTP MCP connectors); connector actions need operator approval.

Desktop
plan-mode❖ Community★ 2

Claude Code-style plan mode on every interactive Hermes surface: /plan or /planmode on blocks mutating Hermes tools dispatched through pre_tool_call (writes outside .hermes/plans, terminal, code execution, delegation, MCP) while the agent explores, asks clarifying questions and writes a plan. The agent submits the plan with plan_mode(submit) and you approve it through Hermes' own approval prompt (gateway buttons, the TUI/Desktop card, the CLI panel or /approve); it then implements in the same turn and tracks todo_list progress. Deny keeps planning and the agent revises. When yolo or approvals.mode: off would auto-approve, it asks one clarify question instead (Approve plan rev N / Keep planning), and only that answer approves. By default plans are compact and decision-complete and the agent does not commit unless asked (plan_style, allow_commits and plan_skill settings; plan_style: core keeps the zero-context /plan craft). The default lean profile keeps compact planning short: a brief planning note, at most three targeted questions, and no todo bookkeeping for short plans (plan_profile: classic keeps 0.3.5); on TUI, Desktop and hermes serve the agent writes the plan once, in its reply, and the plugin saves it. Classic CLI enforced on every supported Hermes; gateway, TUI and Desktop from Hermes v2026.9.24 (0.21.5), and refused on older builds. Disclosure — plan-mode does not enforce Codex app-server exec/applyPatch or TUI /background and btw side agents. It reads eight groups of internal Hermes seams for session identity, workspace, profile and skills.inline_shell, each guarded with a documented fallback. It creates .hermes/plans under the session working directory and keeps per-session state in plugin state. It adds a turn note while planning or executing, a ≤200-char system-prompt hint, and a one-line footer to short replies on chat platforms. When you pick "Always" on a plan approval, Hermes core writes a plugin_rule:plan-mode entry to command_allowlist in config.yaml. With allow_gateway_injection: true it queues one message to start work after a typed /planmode approve. On TUI, Desktop and hermes serve sessions (lean profile, plan_once) it reads the visible reply text from post_api_request while planning and saves its <proposed_plan> block as the plan file. No network calls, no subprocesses, no self-updater.

Tools
hermes-teammates❖ Community★ 1

Named subagent teammates for Hermes: the operator defines a roster (instructions, toolsets, model), and the agent assigns them work, checks results, steers a running teammate, follows up with a digest of earlier results, and can work a Kanban teammates lane with a review handoff. Launches subagents only through the public ctx.subagent_lifecycle API. Stock Hermes; no patched core. Disclosure — adds five tools and a /teammates command; the model picks only a teammate name, and the operator's config decides what it means. Teammates run as in-process Hermes subagents on the parent's provider credentials; toolsets narrow the parent's tools at toolset granularity only (the file toolset includes write_file and patch), and a teammate with invalid settings refuses to launch. A delegated child cannot start teammates. Steering dispatches delegate_task's steer action with the turn-bound parent, so under plugins.isolation: host every tool except the roster refuses. It keeps a per-profile SQLite run ledger in its plugin-data folder (goals, statuses, clipped summaries; no transcripts or credentials). For a card assigned to its non-profile lane, it claims the card through the Kanban DB, heartbeats the claim and its worker, then moves the card to review without a reviewer, or blocks it on failure, a stop or an unavailable result; it never completes a card. It runs one in-process monitor thread per lane run to keep the claim alive; no network calls, child processes or self-updates of its own.

Automation
fish-audio❖ Community★ 0

The official Fish Audio plugin, maintained by Electric Sheep: expressive text-to-speech in 80+ languages, speech-to-text, Fish Audio's community voice library, voice cloning and voice design, with a Voices page in Hermes Desktop. Fish Audio becomes a Hermes speech and transcription provider for voice replies, read-aloud, voice notes and Desktop dictation, with sentence-by-sentence streaming in CLI voice mode and Desktop, and live dictation captions on Hermes 0.21.6+ (stt.streaming: true). Adds the fish_speak, fish_voices and fish_transcribe tools, /fish and hermes fish commands, and three skills. Disclosure — sends your Fish API key and the text, audio (with file names) and voice titles, tags, descriptions, cover images and design instructions you ask it to process to api.fish.audio, or to the base_url you configure, and reads your Fish wallet for balances and model choice; with live dictation on, microphone audio streams to api.fish.audio's realtime speech-to-text endpoint while you speak, billed per committed phrase rounded up to a second; synthesis, transcription, cloning and voice design are paid requests billed to your Fish account, except the free s2.1-pro-free model, whose requests Fish may use to improve its models. The key comes from the profile's secret scope (Hermes stores it in the profile .env; a single-profile install may also read FISH_API_KEY from the environment). Generated audio and subtitles are written to Hermes's audio cache; clone samples and recordings it uploads must be regular audio files, and Hermes config, secret and credential paths are refused. Cloning and deleting voices from chat or the model tools go through Hermes's approval gate and follow your approval settings. The Desktop Voices page and a Fish Audio settings page add gateway routes under /api/plugins/fish-audio/, behind the Hermes dashboard's existing authentication. On the Voices page, previews, clones and voice designs are billed; cloning a voice or saving a designed one creates a voice in your Fish account; cloning and deleting are confirmed on the page (a speaker-consent box, a typed voice name) instead of through Hermes's approval gate; and Use sets the profile's Fish voice, and its speech provider when none is set. The settings page and /fish alias can set or reset the profile's Fish model and voice and save up to 50 voice names in the profile's config. Preview and design audio files are deleted from the gateway once returned; a design's audio is held in gateway memory so you can save it, until it is saved, a later design or save finds it over an hour old, or the gateway stops; clone uploads are deleted after the clone, or by the next upload once idle for 15 minutes. With a key set, Desktop reads your Fish wallet when an agent is selected and about every five minutes, for the status-bar credit; favourites stay in Desktop's plugin storage on that computer, and fetched previews stay in the window's memory until it closes. No telemetry.

Voice
hermes-cloud-file-manager❖ Community★ 0

Cloud Files for Hermes Desktop — browse, search, create folders and bulk-upload files and whole folders to the machine your agent runs on, read and edit its Markdown and text files (view first; nothing is written until you review the line diff and press Save), import files from the agent's own Google Drive, and hand the agent file locations from the chat + menu without re-uploading. Built for remote gateways (token or sign-in); works locally too. Disclosure — adds a file API to the gateway (dashboard plugin routes under the gateway's existing auth) over the agent's working folders, by default terminal.cwd or else the gateway user's home with its dot-entries hidden. It lists and searches those folders, reads Markdown and text files, creates folders and writes uploads and Drive imports (staged as hidden .cfm-* temp files in the destination folder; a name clash keeps both files). It overwrites only an existing .md/.markdown/.txt file you open and explicitly Save in its editor (refused if the file changed since you opened it). It never deletes your files (it removes only its own stale or aborted .cfm-* temp files and staging folders), never follows links out of those folders, and never lists, reads or writes the agent's Hermes home apart from a working folder set inside it (roots, terminal.cwd, or a workspace/ folder it creates when the working folder would be the home itself). Its only network use is Google Drive, read-only, through the agent's own google-workspace skill, whose scripts (from skills/productivity/google-workspace in the agent's Hermes home, else the copy bundled with Hermes) it runs with the gateway's Python and a minimal environment without API keys; the plugin never reads the Google token. While Desktop is open it re-checks Drive sign-in about once a minute; otherwise it makes no network calls.

Desktop

← Back to the catalog · catalog built Oct 13, 2026