Files
hermes-agent/plugins/hermes-achievements
Ben a6e47314f9 fix(dashboard): sanction plugin WS/upload auth via SDK helpers (gated mode)
Dashboard plugins (kanban, hermes-achievements) read
window.__HERMES_SESSION_TOKEN__ directly and hand-assembled WebSocket
URLs with ?token=. That works in loopback/--insecure mode but is
rejected on OAuth-gated deployments, where the session token is absent
and _ws_auth_ok only accepts single-use ?ticket= auth. The result was
401s on plugin REST calls and 1008/403 on the kanban live-events WS
whenever the dashboard ran behind OAuth (e.g. hosted Fly agents).

Make the plugin SDK the single sanctioned auth surface:

- web/src/lib/api.ts: add authedFetch() (raw Response for FormData
  uploads / blob downloads, token-or-cookie auth, no throw / no 401
  redirect) and buildWsUrl() (assembles a ws(s):// URL with the correct
  auth param for the active mode — fresh single-use ticket in gated
  mode, token in loopback).
- web/src/plugins/registry.ts: expose authedFetch, buildWsUrl,
  buildWsAuthParam, and sdkVersion on window.__HERMES_PLUGIN_SDK__;
  add SDK_CONTRACT_VERSION.
- web/src/plugins/sdk.d.ts: hand-authored typed contract for the
  plugin SDK + registry globals (single source of truth for the
  Window declarations).
- plugins/kanban + hermes-achievements dist bundles: stop reading the
  session token directly; route uploads/downloads through
  SDK.authedFetch and the live-events WS through SDK.buildWsUrl.
- plugins/kanban plugin_api.py: _ws_upgrade_authorized() delegates the
  /events WS upgrade to the canonical web_server._ws_auth_ok gate, so
  it transparently accepts loopback token / gated ticket / internal
  credential and can never drift from core auth again.
- tests: guard test asserting no plugin dist reads
  __HERMES_SESSION_TOKEN__ directly; kanban gated-ticket WS test.

Verified live on a gated staging Fly agent: kanban /events upgrades
101 with a minted ticket (ticket_len=43, ws_auth_ok=True) where the
old code got 403.
2026-06-03 16:59:36 -07:00
..

Hermes Achievements

Bundled with Hermes Agent. Originally authored by @PCinkusz at https://github.com/PCinkusz/hermes-achievements — vendored into plugins/hermes-achievements/ so it ships with the dashboard out-of-the-box and stays in lockstep with Hermes feature changes. Upstream repo remains the staging ground for new badges and UI iteration.

When Hermes is installed via pip install hermes-agent or cloned from source, this plugin auto-registers as a dashboard tab on first hermes dashboard launch. No separate install step. See Built-in Plugins → hermes-achievements in the main docs.

Achievement system for the Hermes Dashboard: collectible, tiered badges generated from real local Hermes session history.

Hermes Achievements dashboard

The screenshots use temporary demo tier data to show the full visual range. The plugin itself reads real local Hermes session history by default.

Update notice (2026-04-29): If you installed this plugin before today, update to the latest version. The achievements scan path was refactored for much faster warm loads (snapshot cache + incremental checkpoint scan).

Share cards (2026-05-04, vendored in hermes-agent v0.4.0): Unlocked achievement cards now have a "Share" button that renders a 1200×630 PNG share card (client-side canvas, no backend, no network) with Download + Copy-to-clipboard actions. Fits X/Twitter, Discord, LinkedIn, Bluesky link-preview dimensions.

What it does

Hermes Achievements scans local Hermes sessions and unlocks badges based on real agent behavior:

  • autonomous tool chains
  • debugging and recovery patterns
  • vibe-coding file edits
  • Hermes-native skills, memory, cron, and plugin usage
  • web research and browser automation
  • model/provider workflows
  • lifestyle patterns such as weekend or night sessions

Achievements have three visible states:

  • Unlocked — earned at least one tier
  • Discovered — known achievement, progress visible, not earned yet
  • Secret — hidden until Hermes detects the first related signal

Most achievements level through:

Copper → Silver → Gold → Diamond → Olympian

Each card has a collapsible What counts section showing the exact tracked metric or requirement once the user wants details.

Version 0.2.x expands the catalog to 60+ achievements, including model/provider badges such as Five-Model Flight, Provider Polyglot, Claude Confidant, Gemini Cartographer, and Open Weights Pilgrim.

Examples

  • Let Him Cook
  • Toolchain Maxxer
  • Red Text Connoisseur
  • Port 3000 Is Taken
  • This Was Supposed To Be Quick
  • One More Small Change
  • Skillsmith
  • Memory Keeper
  • Context Dragon
  • Plugin Goblin
  • Rabbit Hole Certified

Install

Clone into your Hermes plugins directory:

git clone https://github.com/PCinkusz/hermes-achievements ~/.hermes/plugins/hermes-achievements

For local development, keep the repo elsewhere and symlink it:

git clone https://github.com/PCinkusz/hermes-achievements ~/hermes-achievements
ln -s ~/hermes-achievements ~/.hermes/plugins/hermes-achievements

Then rescan dashboard plugins:

curl http://127.0.0.1:9119/api/dashboard/plugins/rescan

If backend API routes 404, restart hermes dashboard; plugin APIs are mounted at dashboard startup.

Updating

If you installed with git:

cd ~/.hermes/plugins/hermes-achievements
git pull --ff-only
curl http://127.0.0.1:9119/api/dashboard/plugins/rescan

If the update changes backend routes or plugin_api.py, restart hermes dashboard after pulling.

As of 2026-04-29, updating is strongly recommended because scan performance changed significantly:

  • removed duplicate /overview scan path
  • added cached /achievements snapshot
  • added incremental checkpoint reuse for unchanged sessions

Achievement unlock state is stored locally in state.json and is not overwritten by git updates. New achievements are evaluated from your existing Hermes session history. Achievement IDs are stable and should not be renamed casually because they are the unlock-state keys.

Releases are tagged in git, for example:

git fetch --tags
git checkout v0.2.0

Files

dashboard/
├── manifest.json
├── plugin_api.py
└── dist/
    ├── index.js
    └── style.css

API

Routes are mounted under:

/api/plugins/hermes-achievements/

Endpoints:

GET  /achievements
GET  /scan-status
GET  /recent-unlocks
GET  /sessions/{session_id}/badges
POST /rescan
POST /reset-state

Development

Run checks:

node --check dashboard/dist/index.js
python3 -m py_compile dashboard/plugin_api.py
python3 -m unittest tests/test_achievement_engine.py -v

License

MIT