Skip to main content

hermes-sidepulse

❖ Communityv0.2.0-beta.1★ 0

SidePulse lifecycle status backend; Desktop focus tracking requires the separate companion in the linked setup guide.

Open in Hermes Desktop
hermes plugins install hermes-sidepulse

What it adds

Hooks 11

on_session_starton_session_resetpre_llm_callpre_tool_callpost_tool_callpre_approval_requestpost_approval_responseapi_request_errorpost_llm_callon_session_endon_session_finalize

README

From the reviewed commit 864785d ↗; it updates when the author re-pins.

Hermes SidePulse

Standalone Hermes Agent integration for the SidePulse local status monitor. It contains a Python lifecycle plugin and a Hermes Desktop companion. The Python half observes Hermes lifecycle callbacks; the Desktop half reports the focused local Desktop session through an authenticated dashboard route. No Hermes core patch is required.

Release candidate: 0.2.0-beta.1 (local, not published).

Scope

  • Python plugin: registers the stock Hermes lifecycle hooks declared in python/plugin.yaml in this repository (installed as plugin.yaml) and adds the hermes sidepulse diagnostic command.
  • Desktop companion: follows the focused session only when both the focused owner and the connected Desktop backend are local. Remote focus is skipped.
  • Dashboard backend: exposes authenticated GET /health and POST /activate routes for the Desktop companion. Activation accepts status metadata only.
  • Ordinary hooks: keep their non-Desktop behavior. The Desktop path is an additional activation event; it is not a replacement for normal CLI or gateway lifecycle callbacks.
  • Transport: best-effort local Unix-socket delivery to SidePulse. A missing monitor or unavailable socket does not stop Hermes.

The Desktop folder id is hermes-sidepulse.

Support boundary

  • macOS: automated tests passed locally. The predecessor was live-tested; this exact beta has not replaced the working installation or been hardware-tested.
  • Linux: a CI job is included, but hosted Linux has not yet run.
  • Windows: unsupported because the transport uses Unix-domain sockets.
  • Hermes baseline: Hermes Agent v0.21.3, upstream commit cf7895c1bd9ebbee3c9fc355c552d4d73338a9b4. The installed checkout reported that newer commits were available; they were intentionally not followed for this documentation pass.

See docs/verification.md for the evidence and the test scope and platform limitations.

Prerequisite: SidePulse monitor

Install and set up the SidePulse monitor before enabling this plugin. These are the commands documented by the SidePulse project:

uv tool install git+https://github.com/inteliwear/sidepulse
sidepulse setup

The monitor should be running and accepting the local socket at:

${XDG_STATE_HOME:-${HOME}/.local/state}/sidepulse/agent-monitor/events.sock

The Hermes plugin does not install SidePulse, install hardware support, or start the SidePulse status-bar process.

Manual installation

This repository is intentionally documented for a manual copy. Hermes' native Python plugin manager can enable an installed plugin, but this package's Desktop half is a separate app-local runtime folder. Do not assume a Git installer, a profile copy, or an automatic cross-profile deployment.

1. Copy the Python half

HERMES_HOME defaults to ${HOME}/.hermes. Set it explicitly when targeting a named Hermes profile. SOURCE_DIR is the directory containing this checkout; it is a placeholder and is not part of the installed package layout.

SOURCE_DIR="/path/to/hermes-sidepulse"
HERMES_HOME="${HERMES_HOME:-${HOME}/.hermes}"
PYTHON_PLUGIN_DIR="$HERMES_HOME/plugins/hermes-sidepulse"

test ! -e "$PYTHON_PLUGIN_DIR" || { printf "Destination exists; use the backup/replace procedure below.\n"; exit 1; }
mkdir -p "$PYTHON_PLUGIN_DIR/dashboard" "$PYTHON_PLUGIN_DIR/scripts"
cp "$SOURCE_DIR/python/__init__.py" "$PYTHON_PLUGIN_DIR/"
cp "$SOURCE_DIR/python/bridge.py" "$PYTHON_PLUGIN_DIR/"
cp "$SOURCE_DIR/python/diagnostics.py" "$PYTHON_PLUGIN_DIR/"
cp "$SOURCE_DIR/python/plugin.yaml" "$PYTHON_PLUGIN_DIR/"
cp "$SOURCE_DIR/python/dashboard/manifest.json" "$PYTHON_PLUGIN_DIR/dashboard/"
cp "$SOURCE_DIR/python/dashboard/noop.js" "$PYTHON_PLUGIN_DIR/dashboard/"
cp "$SOURCE_DIR/python/dashboard/plugin_api.py" "$PYTHON_PLUGIN_DIR/dashboard/"

Install the compatibility helper too; hermes sidepulse compat invokes it:

cp "$SOURCE_DIR/python/scripts/check_hermes_compat.py" "$PYTHON_PLUGIN_DIR/scripts/"

Enable the Python plugin with the supported Hermes CLI command:

HERMES_HOME="$HERMES_HOME" hermes plugins enable hermes-sidepulse
HERMES_HOME="$HERMES_HOME" hermes plugins list --user --no-bundled --json
HERMES_HOME="$HERMES_HOME" hermes plugins validate \
  "$PYTHON_PLUGIN_DIR" --json

hermes plugins enable <name>, hermes plugins disable <name>, hermes plugins remove <name>, and hermes plugins validate <path> --json were verified against the stated Hermes baseline. Validation is read-only; it does not install the candidate into the live Hermes home.

2. Copy the Desktop half

Install the Desktop companion once in the Hermes home used by the local Hermes Desktop application. It is an app-local folder, not a per-profile backend copy:

HERMES_HOME="${HERMES_HOME:-${HOME}/.hermes}"
test ! -e "$HERMES_HOME/desktop-plugins/hermes-sidepulse" || { printf "Desktop destination exists; back it up first.\n"; exit 1; }
mkdir -p "$HERMES_HOME/desktop-plugins/hermes-sidepulse"
cp "/path/to/hermes-sidepulse/desktop/plugin.js" \
  "$HERMES_HOME/desktop-plugins/hermes-sidepulse/plugin.js"

The folder name must remain hermes-sidepulse; the file name must remain plugin.js.

3. Restart Desktop's backend after first install

After the first Python/Desktop installation, restart the Hermes Desktop backend before judging the integration. Use Desktop's backend restart control when available; otherwise quit and reopen Hermes Desktop. Later edits to desktop/plugin.js may be hot-reloaded by Desktop, but a first install must be validated after the backend route and Python plugin have been discovered.

For a named profile, repeat the Python copy and enable steps with that profile's HERMES_HOME (normally ${HOME}/.hermes/profiles/<profile>), or use Hermes' --profile <profile> selector with the enable/list commands. This guide makes no automatic cross-profile-install claim, even though the manifest carries profile_scope: shared; verify every profile that is meant to run the Python half.

Configuration

New configuration belongs under plugins.entries.hermes-sidepulse.settings:

plugins:
  entries:
    hermes-sidepulse:
      settings:
        agent_id: Hermes
        # state_dir: /custom/state/sidepulse/agent-monitor
        # socket_path: /custom/state/sidepulse/agent-monitor/events.sock
        # socket_timeout: 0.2
        # log_events: true

The active profile name is used when agent_id is empty. The complete setting defaults, coercions, event fields, and Desktop activation rules are in docs/configuration.md.

Privacy model

The plugin emits status metadata only:

  • hook-derived event name and normalized SidePulse mode;
  • timestamp, provider label, configured display label, and opaque session-scoped status identity;
  • Hermes profile name, durable session id, and turn id when supplied;
  • client surface/origin label; and
  • tool name metadata, never tool arguments or results.

It does not send prompts, transcripts, assistant messages, approval details, tool arguments, tool results, response bodies, or approval routing keys. Final response text is inspected in memory only to choose a final status; it is not placed in the socket event or metadata log. The plugin registers no model-facing tools and adds no tool schema to model prompts.

When log_events is enabled (the default), the plugin appends compact metadata to hermes.jsonl under the SidePulse state directory and enforces owner-only file mode 0600. The package contains no operational logs and must not be published with a user's hermes.jsonl, latest.json, socket, compatibility baseline, or session data.

Status behavior

The Python lifecycle mapping produces these normalized modes:

Mode Meaning
idle_ready Session started/reset or Desktop focus is not running.
working Hermes is processing a prompt or has returned from a successful tool.
tool_running A non-clarification tool is executing.
waiting_for_input Hermes needs approval, clarification, or an explicit final question.
blocked_error An approval was denied, an API request failed, or a tool failure is terminal for the event.
completed A final response or session finalization completed successfully.

A Desktop focus activation preserves an existing waiting_for_input state; it does not turn an outstanding question into idle. See the mapping table in docs/configuration.md.

Diagnose and verify

After the backend restart:

HERMES_HOME="${HERMES_HOME:-${HOME}/.hermes}" hermes sidepulse doctor --json
HERMES_HOME="${HERMES_HOME:-${HOME}/.hermes}" hermes sidepulse test --mode working --json
HERMES_HOME="${HERMES_HOME:-${HOME}/.hermes}" hermes sidepulse test --mode ask --json
HERMES_HOME="${HERMES_HOME:-${HOME}/.hermes}" hermes sidepulse test --mode done --json

Available synthetic modes are idle, working, tool, ask, done, and error. delivered: false means the local SidePulse socket was unavailable; that is an honest transport result, not a failed Hermes turn.

After a Hermes update, run:

hermes sidepulse compat --json

The compatibility command checks the current Hermes version and hook set, the enabled plugin, the SidePulse socket, and synthetic event logging. Do not use it as a reason to patch Hermes core; this plugin is designed to fail closed on missing profile provenance and to keep its observer callbacks non-blocking.

Upgrade, rollback, and removal

Disable the Desktop companion in Settings → Plugins and disable the Python plugin first. Move only the existing plugin folders into a new backup directory; do not overlay an upgrade on old files. Repeat the Python step for each profile that received a copy. Run this block for the local Desktop home:

HERMES_HOME="${HERMES_HOME:-${HOME}/.hermes}"
HERMES_HOME="$HERMES_HOME" hermes plugins disable hermes-sidepulse
BACKUP_DIR="$(mktemp -d "$HERMES_HOME/sidepulse-backup.XXXXXX")"
test ! -d "$HERMES_HOME/plugins/hermes-sidepulse" || \
  mv "$HERMES_HOME/plugins/hermes-sidepulse" "$BACKUP_DIR/python"
test ! -d "$HERMES_HOME/desktop-plugins/hermes-sidepulse" || \
  mv "$HERMES_HOME/desktop-plugins/hermes-sidepulse" "$BACKUP_DIR/desktop"
printf 'Preserved plugin files in %s\n' "$BACKUP_DIR"

For removal, stop here and restart the backend yourself. For an upgrade, follow the fresh installation steps above, enable the Desktop companion again, and restart the backend. Verify the new version before discarding any backups.

For rollback, disable both new components, move them to a different backup, and move the original python and desktop folders back to their respective plugins/hermes-sidepulse and desktop-plugins/hermes-sidepulse locations. Re-enable both components and restart the backend. Keep configuration unchanged unless the release explicitly requires a configuration migration.

Restart the Desktop backend after removal if its backend route is still reachable. Removal does not delete Hermes sessions, SidePulse state, or other plugins. Do not use a broad profile reset, remove all plugins, or delete the SidePulse state directory as part of this bounded removal.

Migration from an older SidePulse core patch

Use the bounded procedure in docs/migration.md. It backs up and removes only the known old SidePulse core edits, disables only the old repair automation, and never performs a broad Hermes reset.

License and provenance

The license and source-history findings are recorded in NOTICE.md. The root LICENSE preserves the upstream SidePulse MIT notice and adds attribution for the standalone changes.

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