Authoring Hermes-Agent Skills (in-repo)
Overview
There are two places a SKILL.md can live:
- User-local:
~/.hermes/skills/<maybe-category>/<name>/SKILL.md — personal, not shared. Created via skill_manage(action='create').
- In-repo (this skill is about this case):
/home/bb/hermes-agent/skills/<category>/<name>/SKILL.md — committed, shipped with the package. Use write_file + git add. skill_manage(action='create') does NOT target this tree.
When to Use
- User asks you to add a skill "in this branch / repo / commit"
- You're committing a reusable workflow that should ship with hermes-agent
- You're editing an existing skill under
/home/bb/hermes-agent/skills/ (use patch for small edits, write_file for rewrites; skill_manage still works for patch on in-repo skills, but not for create)
Required Frontmatter
Source of truth: tools/skill_manager_tool.py::_validate_frontmatter. Hard requirements:
- Starts with
--- as the first bytes (no leading blank line).
- Closes with
\n---\n before the body.
- Parses as a YAML mapping.
name field present.
description field present, ≤ 1024 chars (MAX_DESCRIPTION_LENGTH).
- Non-empty body after the closing
---.
Peer-matched shape used by every skill under skills/software-development/:
---
name: my-skill-name # lowercase, hyphens, ≤64 chars (MAX_NAME_LENGTH)
description: Use when <trigger>. <one-line behavior>.
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
hermes:
tags: [short, descriptive, tags]
related_skills: [other-skill, another-skill]
---
version / author / license / metadata are NOT enforced by the validator, but every peer has them — omit and your skill sticks out.
Size Limits
- Description: ≤ 1024 chars (enforced).
- Full SKILL.md: ≤ 100,000 chars (enforced as
MAX_SKILL_CONTENT_CHARS, ~36k tokens).
- Peer skills in
software-development/ sit at 8-14k chars. Aim for that range. If you're pushing past 20k, split into references/*.md and reference them from SKILL.md.
Peer-Matched Structure
Every in-repo skill follows roughly:
# <Title>
## Overview
One or two paragraphs: what and why.
## When to Use
- Bulleted triggers
- "Don't use for:" counter-triggers
## <Topic sections specific to the skill>
- Quick-reference tables are common
- Code blocks with exact commands
- Hermes-specific recipes (tests via scripts/run_tests.sh, ui-tui paths, etc.)
## Common Pitfalls
Numbered list of mistakes and their fixes.
## Verification Checklist
- [ ] Checkbox list of post-action verifications
## One-Shot Recipes (optional)
Named scenarios → concrete command sequences.
Not every section is mandatory, but Overview + When to Use + actionable body + pitfalls are the minimum for the skill to feel like a peer.
Directory Placement
skills/<category>/<skill-name>/SKILL.md
Categories currently in repo (confirm with ls skills/): autonomous-ai-agents, creative, data-science, devops, dogfood, email, gaming, github, leisure, mcp, media, mlops/*, note-taking, productivity, red-teaming, research, smart-home, social-media, software-development.
Pick the closest existing category. Don't invent new top-level categories casually.
Workflow
Research first, write second — When creating skills about tools/techniques, ALWAYS use web_search, browser, or terminal to check current GitHub repos for latest versions and commands. Do NOT write purely from training data — tools change fast. Training data is a starting point; live verification is mandatory.
Parallel research pattern — Use delegate_task with batch tasks for comprehensive coverage. Split by category (3 concurrent max):
delegate_task(tasks=[
{"goal": "Research GitHub for [category A] tools. Check repos X, Y, Z. Return markdown with versions, install, usage.", "toolsets": ["web", "terminal", "file"]},
{"goal": "Research GitHub for [category B] tools. Check repos A, B, C. Return markdown.", "toolsets": ["web", "terminal", "file"]},
{"goal": "Research GitHub for [category C] tools. Return markdown.", "toolsets": ["web", "terminal", "file"]},
])
Each subagent returns findings inline or as a file. Then create/update skills from the research. If subagents time out, fall back to writing from training data and note the gap.
Do NOT report intermediate status to the user ("Still working...", "Processing...") — just deliver the final result. The user doesn't need play-by-play updates during long research tasks.
Survey peers in the target category:
ls skills/<category>/
Read 2-3 peer SKILL.md files to match tone and structure.
Check validator constraints in tools/skill_manager_tool.py if unsure.
Draft with write_file to skills/<category>/<name>/SKILL.md.
Validate locally:
import yaml, re, pathlib
content = pathlib.Path("skills/<category>/<name>/SKILL.md").read_text()
assert content.startswith("---")
m = re.search(r'\n---\s*\n', content[3:])
fm = yaml.safe_load(content[3:m.start()+3])
assert "name" in fm and "description" in fm
assert len(fm["description"]) <= 1024
assert len(content) <= 100_000
Git add + commit on the active branch.
Note: the CURRENT session's skill loader is cached — skill_view / skills_list will not see the new skill until a new session. This is expected, not a bug.
Cross-Referencing Other Skills
metadata.hermes.related_skills unions both trees (skills/ in-repo and ~/.hermes/skills/) at load time. You CAN reference a user-local skill from an in-repo skill, but it won't resolve for other users who clone the repo fresh. Prefer referencing only in-repo skills from in-repo skills. If a frequently-referenced skill lives only in ~/.hermes/skills/, consider promoting it to the repo.
Editing Existing In-Repo Skills
- Small fix (typo, added pitfall, tightened trigger):
skill_manage(action='patch', name=..., old_string=..., new_string=...) works fine on in-repo skills.
- Major rewrite:
write_file the whole SKILL.md. skill_manage(action='edit') also works but requires supplying the full new content.
- Adding supporting files:
write_file to skills/<category>/<name>/references/<file>.md, templates/<file>, or scripts/<file>. skill_manage(action='write_file') also works and enforces the references/templates/scripts/assets subdir allowlist.
- Always commit the edit — in-repo skills are source, not runtime state.
Common Pitfalls
Using skill_manage(action='create') for an in-repo skill. It writes to ~/.hermes/skills/, not the repo tree. Use write_file for in-repo creation.
Leading whitespace before ---. The validator checks content.startswith("---"); any leading blank line or BOM fails validation.
Description too generic. Peer descriptions start with "Use when ..." and describe the trigger class, not the one task. "Use when debugging X" > "Debug X".
Forgetting the author/license/metadata block. Not validator-enforced, but every peer has it; omitting makes the skill look half-finished.
Writing a skill that duplicates a peer. Before creating, ls skills/<category>/ and open 2-3 peers. Prefer extending an existing skill to creating a narrow sibling.
Expecting the current session to see the new skill. It won't. The skill loader is initialized at session start. Verify in a fresh session or via skill_view using the exact path.
Linking to skills that don't exist in-repo. related_skills: [some-user-local-skill] works for you but breaks for other clones. Prefer only in-repo links.
Verification Checklist
1---2name: hermes-agent-skill-authoring3description: Author in-repo SKILL.md: frontmatter, validator, structure.4license: MIT5---67# Authoring Hermes-Agent Skills (in-repo)89## Overview1011There are two places a SKILL.md can live:12131. **User-local:** `~/.hermes/skills/<maybe-category>/<name>/SKILL.md` — personal, not shared. Created via `skill_manage(action='create')`.142. **In-repo (this skill is about this case):** `/home/bb/hermes-agent/skills/<category>/<name>/SKILL.md` — committed, shipped with the package. Use `write_file` + `git add`. `skill_manage(action='create')` does NOT target this tree.1516## When to Use1718- User asks you to add a skill "in this branch / repo / commit"19- You're committing a reusable workflow that should ship with hermes-agent20- You're editing an existing skill under `/home/bb/hermes-agent/skills/` (use `patch` for small edits, `write_file` for rewrites; `skill_manage` still works for patch on in-repo skills, but not for `create`)2122## Required Frontmatter2324Source of truth: `tools/skill_manager_tool.py::_validate_frontmatter`. Hard requirements:2526- Starts with `---` as the first bytes (no leading blank line).27- Closes with `\n---\n` before the body.28- Parses as a YAML mapping.29- `name` field present.30- `description` field present, ≤ **1024 chars** (`MAX_DESCRIPTION_LENGTH`).31- Non-empty body after the closing `---`.3233Peer-matched shape used by every skill under `skills/software-development/`:3435```yaml36---37name: my-skill-name # lowercase, hyphens, ≤64 chars (MAX_NAME_LENGTH)38description: Use when <trigger>. <one-line behavior>.39version: 1.0.040author: Hermes Agent41license: MIT42metadata:43 hermes:44 tags: [short, descriptive, tags]45 related_skills: [other-skill, another-skill]46---47```4849`version` / `author` / `license` / `metadata` are NOT enforced by the validator, but every peer has them — omit and your skill sticks out.5051## Size Limits5253- Description: ≤ 1024 chars (enforced).54- Full SKILL.md: ≤ 100,000 chars (enforced as `MAX_SKILL_CONTENT_CHARS`, ~36k tokens).55- Peer skills in `software-development/` sit at **8-14k chars**. Aim for that range. If you're pushing past 20k, split into `references/*.md` and reference them from SKILL.md.5657## Peer-Matched Structure5859Every in-repo skill follows roughly:6061```62# <Title>6364## Overview65One or two paragraphs: what and why.6667## When to Use68- Bulleted triggers69- "Don't use for:" counter-triggers7071## <Topic sections specific to the skill>72- Quick-reference tables are common73- Code blocks with exact commands74- Hermes-specific recipes (tests via scripts/run_tests.sh, ui-tui paths, etc.)7576## Common Pitfalls77Numbered list of mistakes and their fixes.7879## Verification Checklist80- [ ] Checkbox list of post-action verifications8182## One-Shot Recipes (optional)83Named scenarios → concrete command sequences.84```8586Not every section is mandatory, but `Overview` + `When to Use` + actionable body + pitfalls are the minimum for the skill to feel like a peer.8788## Directory Placement8990```91skills/<category>/<skill-name>/SKILL.md92```9394Categories currently in repo (confirm with `ls skills/`): `autonomous-ai-agents`, `creative`, `data-science`, `devops`, `dogfood`, `email`, `gaming`, `github`, `leisure`, `mcp`, `media`, `mlops/*`, `note-taking`, `productivity`, `red-teaming`, `research`, `smart-home`, `social-media`, `software-development`.9596Pick the closest existing category. Don't invent new top-level categories casually.9798## Workflow991001. **Research first, write second** — When creating skills about tools/techniques, ALWAYS use `web_search`, `browser`, or `terminal` to check current GitHub repos for latest versions and commands. Do NOT write purely from training data — tools change fast. Training data is a starting point; live verification is mandatory.101102 **Parallel research pattern** — Use `delegate_task` with batch tasks for comprehensive coverage. Split by category (3 concurrent max):103104 ```python105 delegate_task(tasks=[106 {"goal": "Research GitHub for [category A] tools. Check repos X, Y, Z. Return markdown with versions, install, usage.", "toolsets": ["web", "terminal", "file"]},107 {"goal": "Research GitHub for [category B] tools. Check repos A, B, C. Return markdown.", "toolsets": ["web", "terminal", "file"]},108 {"goal": "Research GitHub for [category C] tools. Return markdown.", "toolsets": ["web", "terminal", "file"]},109 ])110 ```111112 Each subagent returns findings inline or as a file. Then create/update skills from the research. If subagents time out, fall back to writing from training data and note the gap.113114 **Do NOT report intermediate status to the user** ("Still working...", "Processing...") — just deliver the final result. The user doesn't need play-by-play updates during long research tasks.1151162. **Survey peers** in the target category:117 ```bash118 ls skills/<category>/119 ```120 Read 2-3 peer SKILL.md files to match tone and structure.1212. **Check validator constraints** in `tools/skill_manager_tool.py` if unsure.1223. **Draft** with `write_file` to `skills/<category>/<name>/SKILL.md`.1234. **Validate locally**:124 ```python125 import yaml, re, pathlib126 content = pathlib.Path("skills/<category>/<name>/SKILL.md").read_text()127 assert content.startswith("---")128 m = re.search(r'\n---\s*\n', content[3:])129 fm = yaml.safe_load(content[3:m.start()+3])130 assert "name" in fm and "description" in fm131 assert len(fm["description"]) <= 1024132 assert len(content) <= 100_000133 ```1345. **Git add + commit** on the active branch.1356. **Note:** the CURRENT session's skill loader is cached — `skill_view` / `skills_list` will not see the new skill until a new session. This is expected, not a bug.136137## Cross-Referencing Other Skills138139`metadata.hermes.related_skills` unions both trees (`skills/` in-repo and `~/.hermes/skills/`) at load time. You CAN reference a user-local skill from an in-repo skill, but it won't resolve for other users who clone the repo fresh. Prefer referencing only in-repo skills from in-repo skills. If a frequently-referenced skill lives only in `~/.hermes/skills/`, consider promoting it to the repo.140141## Editing Existing In-Repo Skills142143- **Small fix (typo, added pitfall, tightened trigger):** `skill_manage(action='patch', name=..., old_string=..., new_string=...)` works fine on in-repo skills.144- **Major rewrite:** `write_file` the whole SKILL.md. `skill_manage(action='edit')` also works but requires supplying the full new content.145- **Adding supporting files:** `write_file` to `skills/<category>/<name>/references/<file>.md`, `templates/<file>`, or `scripts/<file>`. `skill_manage(action='write_file')` also works and enforces the references/templates/scripts/assets subdir allowlist.146- **Always commit** the edit — in-repo skills are source, not runtime state.147148## Common Pitfalls1491501. **Using `skill_manage(action='create')` for an in-repo skill.** It writes to `~/.hermes/skills/`, not the repo tree. Use `write_file` for in-repo creation.1511522. **Leading whitespace before `---`.** The validator checks `content.startswith("---")`; any leading blank line or BOM fails validation.1531543. **Description too generic.** Peer descriptions start with "Use when ..." and describe the *trigger class*, not the one task. "Use when debugging X" > "Debug X".1551564. **Forgetting the author/license/metadata block.** Not validator-enforced, but every peer has it; omitting makes the skill look half-finished.1571585. **Writing a skill that duplicates a peer.** Before creating, `ls skills/<category>/` and open 2-3 peers. Prefer extending an existing skill to creating a narrow sibling.1591606. **Expecting the current session to see the new skill.** It won't. The skill loader is initialized at session start. Verify in a fresh session or via `skill_view` using the exact path.1611627. **Linking to skills that don't exist in-repo.** `related_skills: [some-user-local-skill]` works for you but breaks for other clones. Prefer only in-repo links.163164## Verification Checklist165166- [ ] File is at `skills/<category>/<name>/SKILL.md` (not in `~/.hermes/skills/`)167- [ ] Frontmatter starts at byte 0 with `---`, closes with `\n---\n`168- [ ] `name`, `description`, `version`, `author`, `license`, `metadata.hermes.{tags, related_skills}` all present169- [ ] Name ≤ 64 chars, lowercase + hyphens170- [ ] Description ≤ 1024 chars and starts with "Use when ..."171- [ ] Total file ≤ 100,000 chars (aim for 8-15k)172- [ ] Structure: `# Title` → `## Overview` → `## When to Use` → body → `## Common Pitfalls` → `## Verification Checklist`173- [ ] `related_skills` references resolve in-repo (or are explicitly OK to be user-local)174- [ ] `git add skills/<category>/<name>/ && git commit` completed on the intended branch