YoooClaw tools and APP messaging platform adapter for Hermes Agent
Project description
hermes-plugin
YoooClaw integration for Hermes Agent.
This repository is the Python plugin boundary between Hermes and YoooClaw.
The existing @yoooclaw/cli daemon remains responsible for the shared data
plane: phone notification ingest, recordings, images, credentials,
light-rule storage, and one-shot light control. The Hermes plugin owns both
external WebSocket transports: the original openclaw-service phone Relay and
the broker APP conversation Relay. The CLI daemon runs as a localhost sidecar.
Production plugin artifacts bundle the platform-specific yoooclaw executable
itself. Users do not need a preinstalled CLI, and the plugin does not download
the CLI on first run. The embedded executable is verified and installed into a
plugin-managed path before use.
The release pipeline downloads the four verified native assets from the pinned
cli-v* release in YoooClaw/cli, then creates one Python wheel per
platform. Each wheel carries only its own executable and a SHA-256 manifest:
darwin-arm64
darwin-x64
linux-arm64
linux-x64
The build job emits the wheels, cli-wheel-index.json, and SHA256SUMS once,
then promotes that exact dist/ bundle through the release flow: test OSS
first, production OSS after approval, and finally PyPI / GitHub Release for
stable versions. Installers and channel markers remain environment-specific and
are regenerated at deploy time. This keeps the Git repository small while
guaranteeing that QA verifies the same bytes we later ship.
One-command install
Install the plugin, store the YoooClaw API key, enable the Hermes tool plugin and APP adapter, and restart the gateway:
curl -fsSL https://artifact.yoooclaw.com/hermes-plugin/install.sh | bash -s -- --api-key "ock_..."
The installer requires Hermes Agent >= 0.14.0. Older Hermes builds do not
provide the plugin platform API (PluginContext.register_platform) used by the
APP adapter, so the installer stops with an upgrade message instead of leaving a
half-enabled plugin behind.
The installer writes the shared key to ~/.yoooclaw/credentials.json, removes
stale API-key and legacy local APP authorization environment overrides from
~/.hermes/.env, and ensures both yoooclaw and yoooclaw_app are present in
plugins.enabled in ~/.hermes/config.yaml. Pass --no-enable-app or set
YOOOCLAW_HERMES_ENABLE_APP=0 for a tools-only install. It also installs the
bundled yoooclaw/yc CLI
artifact into ~/.yoooclaw/hermes-plugin/bin, maintains managed shims, and links
those commands next to the detected hermes executable when that directory is
writable. Set YOOOCLAW_HERMES_CLI_LINK_DIR to choose a different link
directory, or YOOOCLAW_HERMES_INSTALL_CLI=0 to skip shell command links. After
the gateway restart, the installer ensures the YoooClaw daemon is running; pass
--no-start-daemon or set YOOOCLAW_HERMES_START_DAEMON=0 to skip that step.
The installer keeps the daemon, openclaw-service Relay tunnel, and APP adapter lifecycle aligned so the APP can connect back to Hermes immediately after install.
Run scripts/install.sh --help for local development options such as
--no-enable-app, --skip-install, --package, --oss-base-url, --version,
--python, and --no-restart. The source-tree installer defaults to PyPI; the
installer uploaded by CI is rendered with the OSS base URL from .env / GitHub
Secrets and installs the matching platform wheel directly from OSS.
Manual install
Stable plugin releases also publish the platform wheels to PyPI. Hermes discovers both entry-point plugins after a normal package install into the same Python environment Hermes uses:
pip install yoooclaw-hermes-plugin
Enabling pip-installed plugins on Hermes 0.15.1 (and earlier). The
hermes plugins enable <name>/disable/listcommands only recognize directory-based (~/.hermes/plugins/) and bundled plugins — they do not scan Python entry points, sohermes plugins enable yoooclawfails with "Plugin 'yoooclaw' is not installed or bundled." The runtime loader does load entry-point plugins, but only when their names appear in theplugins.enabledallow-list. For a pip install, enable them by editing~/.hermes/config.yamldirectly:plugins: enabled: [yoooclaw, yoooclaw_app]Then restart the gateway (
hermes gateway restart). If a future Hermes release teacheshermes plugins enableto recognize entry-point plugins, the CLI commands below will work as written. The one-command installer above applies this config-file enablement automatically.
Release flow
This repository now uses artifact promotion instead of rebuilding at each environment boundary:
- Push to
release/**runstest-oss.ymland uploads a cache-busted build to the test OSS bucket. A second upload refreshes the stable test update channel without replacing the unique install URL. Purepyproject.tomlversion bumps are ignored so a release commit does not double-publish. - Push tag
v*runsrelease.yml:buildcreates the wheels once, writesSHA256SUMS, and stores the bundle as a GitHub Actions artifact.deploy-testpromotes that bundle to the stable test OSS prefix and sends an "RC pending manual promotion" notification with the exact version number to pass into the next step. - After QA signs off, run
promote-prod.ymlmanually (workflow_dispatch) from GitHub Actions. It auto-discovers the successfulrelease.ymlrun forv{version}, downloads that exact artifact, re-verifiesSHA256SUMS, then promotes it to production OSS. Stable releases continue on to PyPI through the existingpypienvironment and then publish the GitHub Release. rollback.ymlis a manualworkflow_dispatchrollback. It repoints thelatestorbetamarker to a previous version and restores the archived installer fromv{version}/installer/install.shwhen that archive exists.
Repository settings still matter:
test/productionenvironment secrets hold the OSS credentials used by the deploy and rollback workflows;OPENCLAW_RELEASE_TOKENstays build-only.- The manual approval fallback is the
promote-prod.ymldispatch itself, so it works even when private-repository required reviewers are unavailable on the current GitHub plan. - The
pypienvironment remains the OIDC boundary for trusted publishing.
Features
- General Hermes plugin: tools, hooks, slash commands, CLI subcommands, skills.
yoooclaw_appplatform adapter: APP messages into Hermes and Hermes replies back to the APP.- Tool bridge: call
yc --format jsonand the daemon localhost HTTP API. - Embedded CLI: ship the target platform's
yoooclawexecutable in the plugin artifact and use PATH lookup only as a local development fallback. - APP transports: keep both hosted WebSockets open in the plugin process. The
broker*.yoooclaw.comconnection carries Hermes APP chat, while theopenclaw-service*.yoooclaw.comconnection carries phone notification, recording, and image relay frames into the local CLI sidecar. - Local relay server and browser chat UI for end-to-end APP conversation tests.
- Notification watcher: use OS file notifications on the active CLI profile's
notifications/directory to feed newly persisted items into the host-side light-rule runtime without adding a daemon event API.
The tool plugin exposes notification, recording, image, Relay, light-control,
light-rule CRUD, daemon status, and doctor tools. The APP platform adapter
connects directly to Relay and translates the existing OpenClaw-compatible
chat.send, chat.history, chat.abort, and sessions.* RPC frames into
Hermes messages and APP-owned session state.
APP Authentication
APP user authentication is enforced by the Relay service. The Hermes plugin no longer keeps a separate local APP user allowlist.
The APP adapter resolves its Relay key from ~/.yoooclaw/credentials.json by
default — the same source the yoooclaw cli / base daemon reads, so the plugin
and the cli stay on the same key. Stale YOOOCLAW_APP_API_KEY /
YOOOCLAW_API_KEY values in the Hermes environment are ignored and stripped by
the installer. YOOOCLAW_APP_RELAY_URL overrides the Relay URL for local or
staging verification.
The APP broker endpoint follows PHONE_NOTIFICATIONS_ENV, matching the CLI's
environment switch:
PHONE_NOTIFICATIONS_ENV |
Relay host |
|---|---|
development |
broker-test.yoooclaw.com |
test |
broker-test.yoooclaw.com |
production (default) |
broker.yoooclaw.com |
development and test share broker-test for now. Unset or unknown values
fall back to production. YOOOCLAW_APP_RELAY_URL still wins over the env-based
selection when set to a custom/local URL; installer-managed hosted test/prod
overrides are stripped so environment switching can own those endpoints.
Switching environments
The base daemon's Relay endpoint is per yoooclaw profile (relay.url in each
profile's config.json). Use env to switch the active profile and restart the
managed daemon/websocket service group in one step:
CLI profiles use openclaw-service*.yoooclaw.com/message/messages/ws/plugin for
the phone data-plane Relay. The broker*.yoooclaw.com/hermes/... endpoints
belong to the yoooclaw_app chat adapter; the installer repairs stale broker
URLs if they were accidentally persisted into CLI profiles.
hermes yoooclaw env # show the active environment + Relay status
hermes yoooclaw env test # switch to the `test` profile and restart the daemon
hermes yc env test # equivalent short alias
hermes yoooclaw env default # switch back to the `default` (prod) profile
/yoooclaw env <profile> and /yc env <profile> do the same from a chat
session. Built-in default, test, and development profiles are initialized
on first use with the matching Relay endpoint. The switch stops the previous
profile's daemon before starting the target's, so exactly one daemon runs; an
unknown profile name fails without disturbing the running daemon. The Relay
apiKey stays account-global (~/.yoooclaw/credentials.json); switch it with
yoooclaw auth set-default-api-key <label> when an environment needs a different
key.
Lifecycle
Hermes manages the YoooClaw CLI daemon plus two hosted WebSockets as one service
group. The CLI daemon runs as a local sidecar in --ingress proxied mode, so it
exposes ingest APIs without opening its own Relay tunnel. The plugin owns:
openclaw-service*.yoooclaw.com/message/messages/ws/pluginfor phone notifications, recordings, images, and daemon egress events.broker*.yoooclaw.com/hermes/message/messages/ws/pluginfor Hermes APP chat and session RPC.
On startup the plugin computes a lifecycle generation from the plugin version,
embedded CLI binary, active profile, Relay environment, openclaw-service URL,
APP broker URL, API-key fingerprint, proxied ingress mode, and the local egress
callback. If a daemon is already running but does not advertise the same
owner=hermes-plugin generation and ingressMode=proxied contract, the plugin
stops it, starts the current embedded CLI daemon, waits for readiness, connects
the broker websocket, and connects the openclaw-service websocket. On shutdown it
disconnects both WebSockets first and then stops the owned daemon.
In proxied mode, openclaw-service Relay frames are forwarded to the daemon's
localhost ingest/gateway endpoints with the same internal relay headers the CLI
dispatcher used (x-openclaw-relay-internal and the api-key label). Daemon
egress events such as recording.status POST back to a token-protected
127.0.0.1 callback owned by the plugin, then the plugin broadcasts them over
the openclaw-service Relay websocket.
Use the lifecycle diagnostics when debugging upgrade or connection problems:
hermes yoooclaw lifecycle status
hermes yoooclaw lifecycle restart
hermes yc lifecycle status
The APP adapter also runs a watchdog while connected. If the daemon disappears
or its generation changes, the adapter restarts the whole service group. If
either hosted websocket remains disconnected past
YOOOCLAW_HERMES_WS_RESTART_AFTER (default 30 seconds), it also restarts the group. Set
YOOOCLAW_HERMES_LIFECYCLE_WATCH_INTERVAL to tune the watchdog interval
(default 5 seconds). Failed recoveries use exponential backoff capped by
YOOOCLAW_HERMES_LIFECYCLE_MAX_BACKOFF (default 60 seconds). If a Relay
connection still fails, the watchdog restores the local daemon independently
and keeps retrying the remote connections, so a transient network outage cannot
leave the daemon stopped.
Logging
The plugin uses an OpenClaw-style file logger in addition to Hermes' normal logging pipeline. Logs are written daily under:
~/.yoooclaw/plugins/yoooclaw-hermes/logs/YYYY-MM-DD.log
Set YOOOCLAW_HERMES_LOG_DIR to override the log directory. Stable releases
redact common secrets, user text, user URLs, emails, phone numbers, bearer
tokens, JWTs, and long hex tokens before writing files or passing records to
Hermes' upstream logging handlers. Versions containing beta keep raw logs for
debugging, matching the OpenClaw plugin behavior. Log files older than 30 days
are pruned automatically; override with
YOOOCLAW_HERMES_LOG_RETENTION_DAYS.
Search recent plugin logs through the Hermes plugin CLI:
hermes yoooclaw logs --keyword relay --from 2026-06-01 --to 2026-06-04 --limit 50
The Hermes-owned foreground daemon still writes its child-process stdout/stderr
to ~/.yoooclaw/hermes-plugin/daemon-fg.log.
Local Relay And Web UI
For local end-to-end testing, run the Bun/Hono relay server instead of the
production Relay, then start the web test client. Both now live in their own
repository: YoooClaw/relay-server.
git clone git@github.com:YoooClaw/relay-server.git
cd relay-server
bun install
bun run dev # relay server on 127.0.0.1:8799
bun run web:dev # web test client on 127.0.0.1:5173
Then point Hermes' APP adapter at it:
export YOOOCLAW_APP_RELAY_URL="ws://127.0.0.1:8799/message/messages/ws/plugin"
export YOOOCLAW_APP_API_KEY="ock-local-dev"
hermes gateway restart
Ensure yoooclaw_app is in the plugins.enabled list in
~/.hermes/config.yaml (see the install note above; for a linked development
checkout under ~/.hermes/plugins/ you can instead run
hermes plugins enable yoooclaw_app).
See the relay-server repository README for the full list of endpoints,
configuration, and the web test client.
Layout
yoooclaw_hermes/ # General Hermes plugin
yoooclaw_app/ # Hermes platform adapter for YoooClaw APP chat
tests/
The local Relay server and its web test client now live in the separate
YoooClaw/relay-serverrepository.
Development
Install uv first, then:
uv sync --dev
uv run pytest
uv build
For local Hermes discovery, link the plugin directories into ~/.hermes/plugins/
and enable them:
ln -s "$PWD/yoooclaw_hermes" ~/.hermes/plugins/yoooclaw
ln -s "$PWD/yoooclaw_app" ~/.hermes/plugins/yoooclaw_app
hermes plugins enable yoooclaw
hermes plugins enable yoooclaw_app
hermes plugins list
References
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yoooclaw_hermes_plugin-0.5.4-py3-none-manylinux_2_17_x86_64.whl.
File metadata
- Download URL: yoooclaw_hermes_plugin-0.5.4-py3-none-manylinux_2_17_x86_64.whl
- Upload date:
- Size: 4.5 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
daf7a3408a66374c797070ab5874e3c22aa096dfac0169818f164be7b6a36082
|
|
| MD5 |
b357463ca9dedd69602401c8b501bfc6
|
|
| BLAKE2b-256 |
dfdb0bbf07cc5b09c58430f7ad59f923ab7d63e525976156b3e4c9229706daf7
|
File details
Details for the file yoooclaw_hermes_plugin-0.5.4-py3-none-manylinux_2_17_aarch64.whl.
File metadata
- Download URL: yoooclaw_hermes_plugin-0.5.4-py3-none-manylinux_2_17_aarch64.whl
- Upload date:
- Size: 4.0 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c2c633e9dfd120c41130dafa1e5f1196e29c8ee79a0d4b116537444aec42663
|
|
| MD5 |
51165c03c588fd373af5670dfa59bb2e
|
|
| BLAKE2b-256 |
ea0c57b6d5b85f3b31ca07d9a2da662eb1baa0b9f7efe7210660452204d52c85
|
File details
Details for the file yoooclaw_hermes_plugin-0.5.4-py3-none-macosx_11_0_x86_64.whl.
File metadata
- Download URL: yoooclaw_hermes_plugin-0.5.4-py3-none-macosx_11_0_x86_64.whl
- Upload date:
- Size: 4.6 MB
- Tags: Python 3, macOS 11.0+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ed2d6afb4972ccb0bf9503e8fb8672549638b1888a6e94d83d6b2d7a06a8eaf
|
|
| MD5 |
8ad8fb45f4215aaec4d1df2d1fabff98
|
|
| BLAKE2b-256 |
b8a13fd9d8dbbde5391b92016eed1bb1df639cc82557dc549274d1b37e6f0843
|
File details
Details for the file yoooclaw_hermes_plugin-0.5.4-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: yoooclaw_hermes_plugin-0.5.4-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 4.1 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e514573d6b7136c1c08fa1e85d5680bc47620351ccbf8a28b57ceb3b0f54b58
|
|
| MD5 |
2294aa857cdcc7691e1bca9d7dff499b
|
|
| BLAKE2b-256 |
877a1de16cb8d73818cfb08854d6d78606f05058ecfc7e3c388b2fb917be5075
|