Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add AtlasOmnia/hermes-custom-pack --skill hermes-desktop-pluginsgit clone --depth 1 https://github.com/AtlasOmnia/hermes-custom-packWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/atlasomnia/hermes-custom-pack/hermes-desktop-plugins)<a href="https://agentmods.dev/skills/atlasomnia/hermes-custom-pack/hermes-desktop-plugins"><img src="https://agentmods.dev/badge/skills/atlasomnia/hermes-custom-pack/hermes-desktop-plugins.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00025 | $0.02292 |
| Opus 5 | $0.00013 | $0.01146 |
| Sonnet 5 | $0.00005 | $0.00458 |
| Haiku 4.5 | $0.00003 | $0.00229 |
Grade A, and why
hermes-desktop-plugins scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 8d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
This is a copy
100% identical to hermes-desktop-plugins — 0 lines differ, which has more behind it and is treated as the original. This page carries a canonical link to it rather than competing with it.
How it starts
The opening of the file, as written. The whole thing — 174 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Hermes Desktop Plugins Skill
Write plugins for the Hermes desktop app: statusbar items, layout panes,
command-palette commands, keybinds, routes, and themes. A plugin is a single
plain-JavaScript ESM file the app loads at runtime — no build step, no repo
changes. A plugin can also talk to its own Python backend namespace
(ctx.rest/ctx.socket → /api/plugins/<id>); the general Python plugin
system (~/.hermes/plugins/) is otherwise documented separately.
Full human reference (every export, area payloads, backend, security):
website/docs/developer-guide/desktop-plugin-sdk.md.
When to Use
- The user asks for a new desktop UI element (a pane, a statusbar widget, a dashboard, a command) without modifying the app itself.
- You want to surface data you compute (via gateway RPC) inside the app.
Prerequisites
- The Hermes desktop app (it loads plugins; the CLI/gateway alone does not).
- Write access to
$HERMES_HOME/desktop-plugins/(usually~/.hermes/desktop-plugins/).
How to Run
- Create
$HERMES_HOME/desktop-plugins/<name>/plugin.jsfromtemplates/plugin.js(relative to this skill directory) — that's~/.hermes/...by default, or~/.hermes/profiles/<profile>/...under a named profile. Keep<name>equal to the pluginid. - The desktop app watches that directory: the plugin loads within a few seconds of the file landing, and every later save hot-reloads it in place. No reload step. (Fallback if it doesn't appear: ⌘K → Reload desktop plugins.)
- If loading fails the app shows a toast naming the error — fix the file and save again.
Quick Reference
The ONLY import surface is @hermes/plugin-sdk (plus react /
react/jsx-runtime, which resolve to the app's own React — write UI with
jsx() calls, not JSX syntax; the file is not compiled).
host.state.*— readonly reactive atoms:activeSessionId,cwd,gateway,model,profile,viewport. Read with.get()in handlers,useValue(atom)in components.host.request(method, params)— gateway JSON-RPC (sessions, config, skills, cron — everything the app uses).host.onEvent(type, fn)— live gateway events ('*'for all). Returns a disposer.host.notify({ kind, message }),host.navigate(path),host.logs(...),host.status(),haptic('tap').ctx.register({ id, area, order?, render?, data? })— contribute UI. Key areas:'statusBar.right'/'statusBar.left'(chips),'panes'(layout zones — settitleanddata: { placement, dock?, width?, height? }; the pane auto-joins a matching zone),PALETTE_AREA(⌘K commands),KEYBINDS_AREA(rebindable actions).- Pane placement:
placement: 'left'|'right'|'bottom'|'main'is the semantic role — the pane stacks (tabs) with existing panes of that role. To land on a specific EDGE instead, adddock: { pane, pos }— the same gesture as dragging onto a pane's drop chip.paneis any pane id (workspaceis the main thread; alsosessions,terminal,files,review,logs),posis'top'|'bottom'|'left'|'right'|'center'. E.g. "below the conversation" =dock: { pane: 'workspace', pos: 'bottom' }— declare aheight(e.g.'200px') so it doesn't take half the zone. - Full PAGES: register
area: ROUTES_AREAwithdata: { path: '/my-page' }and arender— the page mounts in the workspace (main) pane like any built-in view. Make it reachable with a sidebar nav row:ctx.register({ id: 'nav', area: SIDEBAR_NAV_AREA, data: { path: '/my-page', label: 'My Page', codicon: 'project' } })(renders below Artifacts, lights up at the route) — and/or aPALETTE_AREAcommand callinghost.navigate('/my-page'). ctx.storage.get/set/remove— persistence namespaced to your plugin.ctx.i18n.register({ en, ja, ... })— ship your OWN locale bundles, scoped to your plugin (never edit coreen.ts). Values are literal strings or interpolator functions; nested trees are addressed by dot-path. Read them reactively in components withusePluginI18n(id)returningt('key', ...args)(re-renders on a locale switch), or viactx.i18n.tin handlers/stores. Resolution follows the app's active locale, then youren, then the raw key.- Data:
useQuery/useMutation/useQueryClient/queryClient(the app's ONE React Query client — cache, dedupe,refetchInterval, invalidate like core; never hand-roll a poll loop), plusatom/computedfor plugin-local state. - Backend: if the plugin ships a Python
plugin_api.py(under~/.hermes/plugins/<id>/dashboard/, manifest"api": "plugin_api.py"), reach it withctx.rest('/path', { method?, body?, timeoutMs? })and its live twinctx.socket('/events', onMessage)— both scoped to/api/plugins/<id>by construction (traversal rejected).ctx.socketis a no-op on OAuth remotes, so always keep a polling fallback. The Python backend is imported only when the plugin is inplugins.enabledinconfig.yaml(separate from the in-app enable toggle). For gateway-wide data usehost.request/host.onEventinstead. Contribute(mount-scoped): renderjsx(Contribute, { area, id, children })inside a component so page-owned chrome (e.g. a titlebar control inTITLEBAR_AREAS.center) leaves when the page unmounts —ctx.registeris for permanent contributions.defaultEnabled: falseon the default export ships an opt-in plugin: it inventories in Settings → Plugins, off until the user flips it on.- Users manage plugins in Settings → Plugins (enable/disable live, reveal folder). A disabled plugin stays disabled across restarts — don't fight it; the user turned you off.
- UI: the app's design language, importable directly —
Button,Input,Textarea,Select*,Switch,Checkbox,SegmentedControl,Tabs*,Dialog*,ConfirmDialog,DropdownMenu*,ContextMenu*,Popover*,Tip/Tooltip*,Badge,Kbd/KbdGroup,SearchField,ScrollArea,Separator,Skeleton,GlyphSpinner,EmptyState,ErrorState,CopyButton,StatusDot,LogView,Codicon,DecodeText, pluscnandicons.*. Prefer these over hand-rolled elements so the plugin looks native; style with theme vars, never hardcoded colors.
What ships with it
1 file beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 8d ago First seen · 174 lines · 25 tokens per session scan A 79c1efd62aa0
hermes-desktop-plugins is a skill published in the GitHub repository AtlasOmnia/hermes-custom-pack (56 stars, last pushed 24d ago), licensed MIT. It adds 25 tokens to every session and 2,292 once invoked, about $0.0001 per session on Opus 5. A static security scan graded it A with 0 findings. It is 100% identical to hermes-desktop-plugins, differing in 0 lines, and is treated as a copy.
Other skills, from other repositories
cross-browser-typography-qa
Use this skill when web text looks clipped, flattened, wrapped incorrectly, misaligned, or materially different between Chromium and WebKit/Safari. Treat text rendering as both a geometry problem and a visual paint problem: passing DOM bounds does not prove that every glyph is intact.
yao-geoflow-design
Discover, compare, preview, clone, and orchestrate current GEOFlow frontend experiences across the default site and GeoFlow Agent channel sites, including Laravel Blade themes, homepage module/style JSON, leadform conversion modules, theme editor, target-package capabilities, and cross-channel sync planning. Use for…
hermes-desktop-plugins
Write plugins for the Hermes desktop app: statusbar items, layout panes, command-palette commands, keybinds, routes, and themes. A plugin is a single plain-JavaScript ESM file the app loads at runtime — no build step, no repo changes. A plugin can also talk to its own Python backend namespace (ctx.rest/ctx.socket →…
frontend-dataviz
A skill for choosing and creating clear charts from user-provided data, following the Storytelling with Data approach. It matches chart types to tasks such as comparing categories, showing trends, or displaying distributions.
postcss-plugins
Use when postCSS plugin ecosystem — Autoprefixer, cssnano, nesting, custom plugins, preset configuration. Use when working with postcss plugins.
obsidian-theme-dev
CSS/SCSS development patterns for Obsidian themes. Load when working with theme.css, SCSS variables, or CSS selectors.