Skip to content

feat: add Hermes agent adapter (Native Hermes Support)#114

Merged
rohitg00 merged 11 commits intorohitg00:mainfrom
RUFFY-369:feat/hermes-agent-native-support
Apr 21, 2026
Merged

feat: add Hermes agent adapter (Native Hermes Support)#114
rohitg00 merged 11 commits intorohitg00:mainfrom
RUFFY-369:feat/hermes-agent-native-support

Conversation

@RUFFY-369
Copy link
Copy Markdown
Contributor

@RUFFY-369 RUFFY-369 commented Apr 20, 2026

Summary

Hermes Agent (by Nous Research) is a powerful AI agent optimized for tool-calling and agentic reasoning. Previously, using SkillKit with Hermes required manual configuration or "hacking" the Claude adapter due to the shared XML roots.

This PR adds first-class support for the Hermes agent with correct paths, native XML translation markers, and dual-source parity for legacy environments.

Changes

  • Agent Registry: Added hermes agent type to AgentType enum and all related Record types.
  • New Hermes Adapter: Created HermesAdapter (packages/agents/src/hermes.ts) with detection for .hermes/ projects and ~/.hermes/ global environments.
  • Agent Configuration: Added Hermes config to agent-config.ts specifying .hermes/skills/ as the primary directory and AGENTS.md as the instruction file.
  • XML Sync Markers: Implemented <!-- SKILLS_TABLE_START --> markers in generateConfig to enable idempotent updates without overwriting custom system instructions.
  • Instruction Templates: Added Hermes template to AGENT_INSTRUCTION_TEMPLATES with a specific section order (overview, stack, commands, conventions, structure, guidelines).
  • Command Support: Registered Hermes in CommandGenerator with support for .hermes/commands and slash commands.
  • Translator Support: Mapped hermes → xml in the translator format map and updated translateSkillToAll to include Hermes as a target.
  • Legacy Parity: Added native support to the root src/ tree (src/agents/hermes.ts) to maintain 100% parity with legacy research environments.
  • Windsurf Fix: Fixed a minor bug in the Windsurf adapter where it incorrectly targeted AGENTS.md instead of .windsurfrules.

Build Verification

  • @skillkit/core builds successfully.
  • @skillkit/agents builds successfully.
  • Verified syntax parity between packages/ and src/ root.

Test Plan

  • Detection: skillkit sync correctly identifies .hermes/ directories in the workspace.
  • Translation: skillkit translate --to hermes produces valid SKILL.md files in .hermes/skills/.
  • Idempotency: Multiple runs of skillkit sync do not duplicate the <skills_system> block in AGENTS.md.
  • Parity Check: Confirmed that skills synced via the monorepo tools are readable by the legacy src/ adapter.
  • Unit Tests: All 23+ new adapter tests in packages/agents/src/tests/adapters.test.ts pass.

Related Issues

Fixes #113


Open in Devin Review

Summary by CodeRabbit

  • New Features
    • Added Hermes agent support across discovery, config generation/parsing, invocation, translation, and command generation flows.
  • Documentation
    • README updated to include Hermes in the supported agents list.
  • Tests
    • Added and updated tests to cover Hermes and adjusted adapter counts.
  • Bug Fixes
    • Fixed an adapter’s config path so it loads from the correct location.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 20, 2026

@RUFFY-369 is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 336d3e86-fbe7-425c-be71-31e43b65302f

📥 Commits

Reviewing files that changed from the base of the PR and between 27afc45 and b5b251a.

📒 Files selected for processing (5)
  • README.md
  • packages/core/src/agent-config.ts
  • packages/core/src/context/sync.ts
  • packages/core/src/skills.ts
  • packages/mcp/src/tools.ts
✅ Files skipped from review due to trivial changes (3)
  • packages/mcp/src/tools.ts
  • packages/core/src/context/sync.ts
  • packages/core/src/skills.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • packages/core/src/agent-config.ts

📝 Walkthrough

Walkthrough

Adds first-class Hermes agent support: new HermesAdapter (generate/parse/detect/invoke), AgentType/config/discovery mappings, CLI sync marker support, translator/generator wiring, skill discovery paths, tests, and README update across monorepo and legacy src trees.

Changes

Cohort / File(s) Summary
Agent Types & Core Config
packages/core/src/types.ts, src/core/types.ts, packages/core/src/agent-config.ts, packages/core/src/agents/types.ts
Added "hermes" to AgentType, added AGENT_CONFIG.hermes and discovery path .hermes/agents, and mapped hermes format entries.
Adapter Implementation & Registration
packages/agents/src/hermes.ts, src/agents/hermes.ts, packages/agents/src/index.ts, src/agents/index.ts
New exported HermesAdapter (generateConfig, parseConfig, getInvokeCommand, isDetected) and registered it in adapter registry and detect order.
Display Names & Existing Adapter Tweak
packages/agents/src/generic.ts, src/agents/windsurf.ts
Added 'hermes' → 'Hermes' to display names; updated WindsurfAdapter configFile path.
CLI Sync Marker Support
packages/cli/src/commands/sync.ts
Recognize Hermes-specific markers <!-- SKILLS_TABLE_START --> / <!-- SKILLS_TABLE_END --> for config updates.
Translation, Generator & Primer
packages/core/src/skill-translator.ts, packages/core/src/commands/generator.ts, packages/core/src/primer/types.ts, packages/core/src/translator/types.ts
Added hermes as a translation/generation target, AGENT_FORMAT entry, and instruction template (AGENTS.md, xml, sectionOrder includes structure). Mapped hermesskill-md/claude-agent where applicable.
Skill Discovery & Context Sync
packages/core/src/context/sync.ts, packages/core/src/skills.ts, packages/mcp/src/tools.ts
Include .hermes/skills in discovery paths and agent dir maps so skills under that folder are found.
Tests & Docs
README.md, packages/agents/src/__tests__/adapters.test.ts, tests/agents.test.ts
README expanded agent list and count; tests updated to expect additional adapter and new HermesAdapter unit tests for generate/parse and adapter properties.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI
    participant Detect as detectAgent()
    participant Hermes as HermesAdapter
    participant FS as FileSystem
    participant Sync as updateConfigContent()
    participant Gen as generateConfig()

    CLI->>Detect: request agent detection
    Detect->>Hermes: isDetected()
    Hermes->>FS: check .hermes (cwd / home) and AGENTS.md
    FS-->>Hermes: exists? (true/false)
    Hermes-->>Detect: detection result
    Detect-->>CLI: selected agent (hermes)
    CLI->>Sync: updateConfigContent(skills, hermes markers)
    Sync->>Gen: generateConfig(enabledSkills)
    Gen->>Gen: filter enabled skills & createSkillXml blocks
    Gen-->>Sync: return <skills_system> XML with <!-- SKILLS_TABLE_START/END -->
    Sync->>FS: write/update AGENTS.md between markers
    FS-->>CLI: sync complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰
I nibble XML leaves by lamplight bright,
Markers set so skills hop into sight,
AGENTS.md hums with a new Hermes tune,
I thump my foot — sync finishes soon. ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning One minor out-of-scope change: Windsurf adapter's configFile was modified from 'AGENTS.md' to '.windsurf/rules/skills.md', which appears unrelated to Hermes support objectives. The Windsurf configFile fix should be in a separate PR to keep this change focused on Hermes support. If intentional, clarify the rationale in the PR description or commit message.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add Hermes agent adapter (Native Hermes Support)' clearly and specifically describes the main change: introducing a new Hermes agent adapter to the codebase.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from issue #113: dedicated HermesAdapter with XML support, idempotent sync markers, AGENTS.md management, translation targets, and parity across packages.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Legacy sync command missing hermes markers causes config duplication on re-sync (src/commands/sync.ts:111-124)

The PR adds the hermes agent to the legacy codebase (src/agents/hermes.ts, src/agents/index.ts) but does not add hermes-specific markers to the legacy src/commands/sync.ts:111-124 updateConfigContent function. The packages version at packages/cli/src/commands/sync.ts:217-220 was correctly updated with hermes markers (SKILLS_TABLE_START/SKILLS_TABLE_END), but the legacy version was not. When the legacy sync path is used for hermes, markers[agentType] is undefined, so it falls back to markers.universal which uses SKILLKIT_SKILLS_START/SKILLKIT_SKILLS_END. These don't match the SKILLS_TABLE_START/SKILLS_TABLE_END markers generated by the hermes adapter's generateConfig() (src/agents/hermes.ts:30,50). On re-sync, the function won't find existing markers in the file and will append a second copy of the config instead of replacing the existing one.

View 10 additional findings in Devin Review.

Open in Devin Review

Copy link
Copy Markdown
Owner

@rohitg00 rohitg00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Verified locally at commit 27afc45. Build + typecheck clean, all targeted tests pass.

Validation

  • pnpm -F @skillkit/core build → ok
  • pnpm -F @skillkit/agents build → ok
  • pnpm -F @skillkit/core typecheck → ok
  • pnpm -F @skillkit/agents typecheck → ok
  • @skillkit/agents test → 192/192 pass (3 new Hermes cases in adapters.test.ts)
  • @skillkit/core test → 1035/1035 pass
  • tests/agents.test.ts → 28/28 pass

Good calls

  • parseConfig scopes the <name> regex to SKILLS_TABLE_START/END markers — strictly better than the Clawdbot parser which greedy-matches any <name> tag in the whole file. Test case should ignore <name> tags outside of sync markers verifies this.
  • Sync-marker wiring in packages/cli/src/commands/sync.ts gives idempotent updates.
  • 17 touchpoints wired (vs OpenClaw's 8) — types, agent-config, discovery paths, format map, translator map, primer template, command generator, commands/sync, legacy src/ mirror.
  • Windsurf configFile correction (AGENTS.md.windsurf/rules/skills.md) aligns the legacy src/ tree with packages/core/src/agent-config.ts which already had the modern path.

Nits (non-blocking)

  1. MCP runtime discovery gappackages/mcp/src/tools.ts AGENT_DIR_MAP (line ~184) lists every other agent but not hermes. MCP server's getLocalSkillDirs won't pick up .hermes/skills at runtime. Please add:

    'hermes': ['.hermes/skills'],
  2. README count driftREADME.md:221 adds Hermes row. Collapsed line still reads Plus 34 more. Adapter count moved 45→46 in tests; consider reconciling the README blurb or dropping the fixed number.

  3. XML format assumption — upstream Hermes Agent (NousResearch/hermes-agent v0.10.0) uses Markdown + YAML for SOUL.md/AGENTS.md/MEMORY.md. XML-wrapped blocks inside AGENTS.md are tolerated by Claude-family parsers but not an upstream convention. Matches Clawdbot precedent, so fine to ship — just worth flagging in case the Hermes maintainers prefer a Markdown-only variant later.

Approve once (1) is addressed.

rohitg00 added a commit that referenced this pull request Apr 21, 2026
#117)

* fix(openclaw): align paths with upstream openclaw/openclaw conventions

- skillsDir: 'skills' -> '.openclaw/skills' (match project-scoped convention)
- configFile: 'CLAUDE.md' -> 'AGENTS.md' (upstream uses AGENTS.md/SOUL.md)
- globalSkillsDir: '~/.openclaw/skills' -> '~/.openclaw/workspace/skills'
- altSkillsDirs: keep 'skills' for back-compat, add workspace variant
- isDetected: also check project .openclaw/ and global workspace/
- MCP AGENT_DIR_MAP: .openclaw/skills for runtime discovery
- README: reflect real paths

Refs NousResearch upstream layout; pairs with #114 Hermes support.

* fix(openclaw): address review findings for discovery + detection

- skills.ts: add '.openclaw/skills' to SKILL_DISCOVERY_PATHS (alphabetical)
- config.ts: getSearchDirs prefers globalSkillsDir for home path
  (was deriving from skillsDir, producing ~/.openclaw/skills instead
  of ~/.openclaw/workspace/skills)
- agent-config.ts: add altConfigFiles to AgentDirectoryConfig schema,
  set openclaw altConfigFiles: ['openclaw.json']
- context/sync.ts: detectAgents also iterates altConfigFiles so
  projects with only openclaw.json still detected
- mcp/tools.ts: AGENT_DIR_MAP includes '.openclaw/workspace/skills'
  for home-rooted global discovery
# Conflicts:
#	README.md
@rohitg00
Copy link
Copy Markdown
Owner

Pushed to your branch (maintainer edit) to keep attribution:

Merged main — resolved README conflict. Main restructured the agent table into "Top 11" + "Plus 34 more" collapsed list. Hermes added to the "Plus 34 more" list, count bumped to 35.

Review-driven additions:

  • packages/core/src/skills.ts.hermes/skills added to SKILL_DISCOVERY_PATHS (alphabetical between .goose/skills and .kilocode/skills). Without this, findAllSkills / getLocalSkillDirs would skip .hermes/skills during discovery.
  • packages/mcp/src/tools.tshermes: ['.hermes/skills'] added to AGENT_DIR_MAP. Enables MCP skillkit_catalog / skillkit_load to find Hermes skills when agent=hermes filter is set.

Validation: @skillkit/core build + typecheck + 1035/1035 tests pass. @skillkit/agents build + typecheck + 192/192 tests pass (your 3 new Hermes cases included).

#117 already landed the OpenClaw upstream path alignment with the same pattern, so the infra this PR touches is now consistent across both agents. Ready to merge.

@rohitg00 rohitg00 merged commit a974515 into rohitg00:main Apr 21, 2026
1 of 3 checks passed
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

View 10 additional findings in Devin Review.

Open in Devin Review

Comment thread src/agents/index.ts
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Missing export * from './hermes.js' in src/agents/index.ts

The HermesAdapter is imported at line 20 and added to the adapters record at line 59, but export * from './hermes.js' is not added to the re-exports (lines 22-39). Every other adapter in this file has a corresponding export * statement. This means consumers who import from src/agents/index.ts cannot access HermesAdapter directly. The equivalent file packages/agents/src/index.ts:45 correctly includes the re-export.

(Refers to line 39)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +217 to +220
hermes: {
start: '<!-- SKILLS_TABLE_START -->',
end: '<!-- SKILLS_TABLE_END -->',
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Repeated skillkit sync --agent hermes duplicates </skills_system> closing tag each time

The new hermes entry in updateConfigContent at packages/cli/src/commands/sync.ts:217-220 uses <!-- SKILLS_TABLE_START/END --> markers. When existing content already contains these markers (i.e., any re-sync), the update logic at lines 228-233 concatenates: (1) existing content before start marker, (2) newConfig.slice(newConfig.indexOf(startMarker)) which includes everything after the end marker (\n\n</skills_system>), and (3) existing.slice(endIdx + endMarker.length) which also captures \n\n</skills_system>. This produces a duplicate </skills_system> tag, and the duplication accumulates with every subsequent sync, progressively corrupting the config file.

Trace of the duplication

The HermesAdapter.generateConfig() output (packages/agents/src/hermes.ts:32-58) has content after the end marker:

<!-- SKILLS_TABLE_END -->

</skills_system>

So newConfig.slice(newConfig.indexOf('<!-- SKILLS_TABLE_START -->')) includes </skills_system> at the end, and existing.slice(endIdx + endMarker.length) also yields \n\n</skills_system>. Both get concatenated.

Prompt for agents
The updateConfigContent function in packages/cli/src/commands/sync.ts has a bug where the agent-specific marker replacement path (lines 228-233) duplicates content that appears after the end marker. When newConfig contains content after the end marker (like </skills_system> for hermes and claude-code), both newConfig.slice(newConfig.indexOf(startMarker)) and existing.slice(endIdx + endMarker.length) include that trailing content, causing duplication.

The fix should ensure that when slicing from newConfig, only the content between (and including) the start and end markers is taken, OR the existing content after the end marker is not appended. One approach: find the end marker in newConfig and use newConfig.slice(newConfig.indexOf(startMarker), newConfig.indexOf(endMarker) + endMarker.length) instead of slicing to the end. This would preserve the existing file's structure outside the markers while replacing only the content within them.

This affects both the new hermes entry and the pre-existing claude-code entry which share the same marker pattern.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@rohitg00 rohitg00 mentioned this pull request Apr 21, 2026
pull Bot pushed a commit to Stars1233/skillkit that referenced this pull request Apr 21, 2026
Includes:
- v1.24.0 across all publishable packages
- Add packages/mcp + packages/api to bump-version.sh (were drifting)
- Regenerate assets/tags/v1.24.0.svg, remove stale v1.23.0.svg
- Bump agent count references from 45 to 46 (adds Hermes)
- Update gen-tags.mjs (version + agent count)
- Sync onboarding logo test expectation

Release covers rohitg00#114 (Hermes native support) + rohitg00#117 (OpenClaw upstream paths).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Native Hermes Agent support

2 participants