Skip to main content

boardstate

❖ Communityv1.5.1★ 11

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.

Open in Hermes Desktop
hermes plugins install boardstate

Screenshots

What it adds

Tools 19

boardstate_workspace_getboardstate_tab_createboardstate_tab_updateboardstate_tab_deleteboardstate_tabs_reorderboardstate_widget_addboardstate_widget_updateboardstate_widget_moveboardstate_widget_removeboardstate_layout_setboardstate_workspace_replaceboardstate_undoboardstate_widget_catalogboardstate_design_reviewboardstate_tool_searchboardstate_widget_scaffoldboardstate_data_readboardstate_connector_readboardstate_connector_invoke

README

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

Boardstate for Hermes

Boardstate gives Hermes a durable board that the agent can build with native tools. Open the Board tab in hermes dashboard or the Board page in Hermes Desktop, then ask Hermes to create tabs, add widgets, arrange a layout, or review its design. Widgets include notes, markdown, tables, charts, KPI cards, live Hermes data, and approvals. Changes are stored as a validated workspace document and appear live when the dashboard socket is available.

Boardstate is one unified Hermes plugin: the agent tools, Web dashboard tab, Python backend, Desktop page, and loopback Node sidecar install from this repository together.

Install

Boardstate requires Hermes 0.21.2 or newer and Node.js 20 or newer. Boardstate looks for Node in HERMES_NODE_BIN, then in Hermes' own Node lookup, then on PATH.

hermes plugins install boardstate --enable

This installs the catalog entry at its reviewed pin, and Hermes accepts the scanner's caution verdict for that pin without a prompt. The bare name resolves only after the Hermes plugin catalog lists Boardstate; until then, use the owner/repo form below.

The owner/repo form (hermes plugins install 100yenadmin/boardstate-hermes-plugin) is not reviewed or pinned. It prints the scanner findings and asks for confirmation; pass --force to accept them non-interactively, and --ref <40-character sha> to pin a commit.

To enable an installed copy later:

hermes plugins enable boardstate

Start hermes dashboard for the Web tab. The unified package also contributes a Desktop plugin; enable Boardstate under Capabilities → Plugins in Hermes Desktop. The two surfaces have separate enable switches by design.

After you update or reinstall the plugin, quit and reopen Hermes Desktop. Rescan under Capabilities → Plugins copies the new Desktop files, but a Desktop plugin that is already loaded keeps running its old code until the app restarts.

Profiles

On Hermes 0.21.x, hermes -p <name> dashboard re-runs as the default profile with --open-profile <name>. Web dashboard plugins load from the root ~/.hermes/plugins, and their state comes from the dashboard process's HERMES_HOME, so the web Board tab shows the default profile's board. Install with hermes plugins install … (no -p) for the dashboard, and with hermes -p <name> plugins install … for that profile's agent tools. Hermes Desktop loads the Desktop half app-wide from ~/.hermes/desktop-plugins once you switch it on under Capabilities → Plugins, and talks to the active profile's backend.

Uninstall

Run hermes plugins remove boardstate. The board itself stays in the boardstate-state directory of the profile's Hermes home: $HERMES_HOME when you set it, otherwise ~/.hermes for the default profile and ~/.hermes/profiles/<name> for a named profile. If you set BOARDSTATE_HERMES_STATE_DIR, the board is in that directory instead. Delete it if you no longer need the board.

Native agent tools

No hand-written mcp_servers entry is needed. The package registers these 19 tools in the boardstate toolset:

  • boardstate_workspace_get
  • boardstate_tab_create, boardstate_tab_update, boardstate_tab_delete, boardstate_tabs_reorder
  • boardstate_widget_add, boardstate_widget_update, boardstate_widget_move, boardstate_widget_remove
  • boardstate_layout_set, boardstate_workspace_replace, boardstate_undo
  • boardstate_widget_catalog, boardstate_design_review, boardstate_widget_scaffold, boardstate_data_read
  • boardstate_tool_search, boardstate_connector_read, boardstate_connector_invoke

The two connector invocation tools and boardstate_tool_search are always discoverable. Without an operator-authored connector configuration they return a clear no connectors configured error.

The existing Streamable HTTP MCP endpoint remains available as an optional compatibility path at /api/plugins/boardstate/mcp, but normal Hermes use should rely on the native tools.

What runs

Boardstate starts one Node sidecar on an ephemeral 127.0.0.1 port. Every spawn gets a random nonce. Its mode-0600 port record contains the port, nonce, process id, and owner kind so the agent and dashboard do not create competing writers.

  • An agent tool call can start the sidecar without the dashboard. That sidecar gets no operator secret at all, so operator-only verbs are unavailable until the dashboard replaces it. On it, boardstate_connector_invoke still runs approved readOnly connector tools; a mutating tool asks the agent to open the Board tab instead of parking.
  • When the dashboard finds an agent-owned sidecar, it terminates and replaces that process with a dashboard-owned one. Both use the same state directory, so the board survives.
  • An agent-owned sidecar is stopped when its owner exits if no live agent process adopted it. A process never stops a sidecar whose port record has moved to another spawn.
  • If every process named in the sidecar's port record (its owner and any adopters) dies without cleaning up, for example after SIGKILL, the sidecar notices within a few seconds and shuts itself down.
  • Live Hermes data widgets use the authenticated dashboard API. When only the agent half is running, they show an explicit "open the Board tab" unavailable message instead of crashing.

The Desktop plugin stays inside the public plugin SDK. It uses ctx.register with ROUTES_AREA and SIDEBAR_NAV_AREA for the page and its nav row, ctx.rest for Boardstate requests, ctx.socket for server pushes, ctx.onDispose for cleanup, ctx.setTimeout when the SDK provides it (with a disposed fallback timer on older SDKs), and host.notify for template errors. OAuth remotes support request/response traffic but the SDK intentionally provides no live socket there, so the page reports live updates unavailable instead of pretending to be live.

Network and security disclosure

Boardstate makes no third-party network request by default.

  • The sidecar, dashboard bridge, native tool wrapper, and optional MCP path communicate on loopback only. Live Hermes widgets call the local Hermes dashboard API.
  • External connectors are opt-in. Only an operator-authored $HERMES_HOME/boardstate-state/boardstate.connectors.json can enable one. A connector may spawn its configured local command or contact its configured remote MCP URL; those are the only runtime paths that can reach outside Hermes.
  • Connector reads require an approved grant. Connector mutations park for an operator decision. A changed connector manifest re-pends its grant. A mutation whose wait times out is reported as parked, but a later confirm can still run it, so the agent is told not to retry it on its own (a retry can run the mutation twice) and to ask the operator for the outcome.
  • Operator approve/confirm/deny verbs use a separate in-memory secret that is never written to the port record. In gated multi-user mode, boardstate.operators.json is also required.
  • Sidecar traffic never goes through an HTTP(S)_PROXY from the environment.
  • The sidecar inherits the Hermes process environment, so provider keys there are available to connector env references. A dashboard-owned sidecar also receives the dashboard session token so live Hermes data widgets can read the local dashboard API.
  • Limit of the operator gate. It keeps approvals off the agent's tool surface: no boardstate_* tool, MCP call or board WebSocket can approve or confirm anything. It is not a boundary against an agent that has unrestricted shell access as the same OS user. In ungated loopback mode, such an agent can read the dashboard page, which carries the dashboard session token. In any mode, it can read a same-user process's environment, including the dashboard-owned sidecar's operator secret. If approvals must hold against the agent itself, run the agent's terminal in an isolated backend (for example Docker, SSH or Modal) or as a different OS user from the dashboard.
  • Approved custom widgets run in an opaque-origin iframe with a no-network Content Security Policy. Pending, rejected, and unknown widget assets all return 404.

Connector configuration

Connectors are optional. For example, after installing OfficeCLI, an operator can create:

{
  "connectors": [
    { "name": "officecli", "transport": "stdio", "command": "officecli", "args": ["mcp"] }
  ]
}

Save that as $HERMES_HOME/boardstate-state/boardstate.connectors.json, restart the dashboard, and approve only the requested tools you want. See docs/connectors/officecli.md.

Connector grants are scoped to the active Hermes profile: Boardstate keeps separate state for each HERMES_HOME/profile, while sessions within one profile are the same agent and intentionally share native-tool grants.

Security scanner notes

hermes plugins validate reports caution. All five HIGH findings are in the committed dashboard/sidecar/server.js bundle, which is generated from the pinned packages in package-lock.json. Line numbers are for the 1.5.0 build; reviewers should still inspect every warning:

  • dump_all_env at server.js:3082: ajv's compiler (ajv/dist/compile) names a schema environment variable env (env = env || new SchemaEnv(...)). It does not touch process.env.
  • dump_all_env at server.js:7124: path-key reads the name of the PATH key from process.env.
  • dump_all_env at server.js:7144: cross-spawn resolves a connector command against process.env (PATH).
  • path-key and cross-spawn are transitive dependencies of the MCP SDK's stdio client. None of these returns the environment to an agent.
  • exfil_service at server.js:28509: the optional Pipedream preset URL string in the bundled @boardstate/broker package. It is inert until an operator authors and approves that connector.
  • sudo_usage at server.js:25999: a comment in the MCP SDK's stdio client ("inspired by the default env inheritance of sudo"), not a command Boardstate executes.

The MEDIUM and LOW findings are:

  • Character-code, base64, Unicode-escape and relative-path matches in the minified bundles: server.js, dashboard/dist/index.js, dashboard/vendor/boardstate-browser.js and desktop/plugin.js.
  • One oversized-file warning, for server.js only.
  • The repository's own CI install steps (pip install, git clone in .github/workflows/ci.yml).
  • subprocess use in test/.
  • An example loopback dashboard address in a comment in dashboard/sidecar/src/hermes-data.ts.

Catalog self-updater check: the catalog CI flags a bundled JS file that contains both a GitHub raw-content URL and a file-write call. In the sidecar bundle, the only such URL was ajv's $data meta-schema identifier (its $id and the one $ref to it), which is never fetched. build.mjs rewrites that identifier consistently to https://ajv.js.org/refs/data.json#, so the check stays meaningful for this bundle: a later releases/latest or raw.githubusercontent.com URL next to a file write would still trip it. This repository's CI replays the check, with upstream's exact file enumeration, on every build. Boardstate has no updater; updates arrive only through a new catalog pin plus hermes plugins update boardstate.

dangerous scanner results are not accepted. Reproduce the reviewed artifacts with:

npm ci && npm run build && git diff --exit-code

Development and tests

The build produces the Web bundle, root desktop/plugin.js, sidecar bundle, vendored Lit assets, and dashboard/tools.schema.json. The schema is generated from the same Boardstate tool factory and connector definitions the sidecar invokes.

CI keeps the existing sidecar, connector, operator, widget, theme, Web, Desktop, and Python tests. It also pins Hermes upstream commit 38c289c0146ed8c8b2b767eca1fff6f5b7e6382e and runs plugin validate, doctor, compat, native-tool dispatch, WebSocket auth, and the schema sync gate.

Screenshots

A board built by the agent through the native tools, in the Web Board tab:

Boardstate Board tab in the Hermes web dashboard

The same kind of board on the Board page in Hermes Desktop:

Boardstate Board page in Hermes Desktop

License

MIT — see LICENSE.

fish-audio❖ Community★ 102

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
plan-mode❖ Community★ 98

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★ 78

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
heartbeat2❖ Community★ 4

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. Disclosure — wakes and watchers run full turns on the conversation's own model, billed like any message, at your conversation's context size, with the conversation's normal tools and approval prompts; the agent can arm wakes and watchers itself unless you set agent_can_create to ask_first or no; command watchers run allowlisted read-only commands (default gh pr view/checks, gh run view/list, git ls-remote/status/log) without an approval prompt, with no shell, a sanitized environment (no provider keys, GH_TOKEN or GITHUB_TOKEN) and the process group killed after 30 s, can use your stored git/gh credentials, and `git ls-remote <url>` / `gh -R` can contact any host your machine can reach; URL watchers make the GET requests you or the agent configured, without URL credentials, cookies, auth headers or proxies, always refuse cloud-metadata addresses and refuse private or local addresses unless url_allow_private is on; file watchers refuse paths Hermes blocks from reading; notes, summaries and event payloads are stored in plaintext in the profile's plugin-data; no telemetry.

Automation
hermes-cloud-file-manager❖ Community★ 3

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 15, 2026