| name | publish-hermes-skill-repo |
| description | Publish a local Hermes skill as a public GitHub repo, protect its main branch with required CI, version it, and reinstall it natively with hub provenance. Use when the user says "publish this skill to GitHub", "make a skill repo with CI", "add branch protection to a skill repo", "version a Hermes skill", "release a skill", "reinstall the skill from GitHub", or "turn this skill into an open-source repo", even if they do not say "Hermes" explicitly. Do NOT use for authoring skill content (use building-deterministic-skills), generic repo creation unrelated to skills (use github-repo-management), or installing third-party skills you did not author (use hermes-skill-operations).
|
| license | Apache-2.0 |
| version | 0.1.0 |
| metadata | {"hermes":{"tags":["hermes","skills","github","ci","release","branch-protection"],"related_skills":["building-deterministic-skills","hermes-skill-operations","github-repo-management"]}} |
Publish, protect, version, and reinstall a Hermes skill repo
Take a local Hermes skill directory and ship it as a public, contribution-ready
GitHub repo: Apache-2.0 license, CI that runs the skill's own validators,
branch protection requiring CI, a versioned release, then a clean native
reinstall from GitHub so the installed copy is hub-tracked and commit-pinned.
CRITICAL RULES
- The repo name MUST equal the skill's frontmatter
name. On install the repo
name becomes the skill directory, and Hermes enforces name == directory.
A mismatch fails validation. Confirm both match before gh repo create.
- NEVER hand-edit the Hermes
config.yaml (under ~/.hermes/) — it is a
protected file. Use hermes plugins enable/disable and hermes CLI
commands only.
- NEVER commit
.git/, __pycache__/, caches, or reports/ scrape junk into
the published tree via a raw copy. Stage with git archive HEAD | tar -x
so only committed files ship.
- Reinstall ONLY through Hermes' quarantine APIs (
scan_skill →
should_allow_install → install_from_quarantine), NEVER by copying into
~/.hermes/skills/. The quarantine path writes hub lock provenance, content
hashes, and audit logs.
- A reinstall MUST be blocked unless
should_allow_install(result) returns
True. If the verdict is dangerous, stop. If caution blocks a community
source, sanitize the false positives (see reference) instead of forcing.
- Run the Hermes venv Python for all scan/install steps:
/Users/kiren/.hermes/hermes-agent/venv/bin/python3. System python3 (3.9)
cannot import Hermes modules that use 3.10+ syntax.
- Wait for GitHub CI to pass on the pushed commit BEFORE tagging a release or
reinstalling. Tag and install only commit-verified-green code.
- Offload counting, scan verdicts, and frontmatter checks to the scripts in
scripts/; do not eyeball them.
- If a required fact is missing (skill path, GitHub owner, repo name, version),
output
INSUFFICIENT CONTEXT: <field> and stop instead of guessing.
Gotchas
- Repo named
<skill>-repo or any suffix: WRONG. The install would fail the
name == directory check. Name the repo exactly <skill-name>.
- Bare
owner/repo or owner/repo/. install often fails for root-level skill
repos with "Could not fetch ... from any source" even though inspect
succeeds. Use the quarantine install fallback in the reference, not --force.
- Scanning the LOCAL git worktree inflates findings:
scan_skill recurses into
.git/. Always scan the git archive staged tree (no .git), which is what
actually installs.
caution verdict on community source blocks install. Common false positives:
the literal word "context" tripping context_exfil; invisible/zero-width
Unicode in scraped JSON tripping invisible_unicode. Sanitize, do not force.
- Hand-editing
config.yaml to enable a plugin: blocked (protected file).
enforce_admins=true blocks YOUR direct pushes too. Default to false so
admins keep direct-push convenience while contributor PRs stay gated.
- fish shell cannot do
VAR=$(...) or heredocs. Use bash for variable capture
and write_file for scripts; wrap CLI that needs profile env in
/opt/homebrew/bin/fish -lc '...'.
One-term-per-concept
- SKILL DIR = the local
~/.hermes/skills/<name>/ directory.
- STAGE = a clean
git archive export with no .git (what gets scanned/installed).
- HUB INSTALL = install via quarantine APIs that writes
.hub/lock.json.
- CI GATE = the GitHub Actions checks required by branch protection.
Prerequisites
gh auth status shows a logged-in account with repo and workflow scopes.
- The skill already passes its own validators locally (author it first with
the building-deterministic-skills skill).
- You know: the skill directory, the GitHub owner, the repo name (= skill
name), and the version string (default
0.1.0).
Ordered workflow
Default path: stage a clean copy, scaffold OSS files + CI, push, protect, tag,
reinstall. Read references/publish-commands.md for the full copy-paste
recipes. Progress:
- If the skill directory, GitHub owner, repo name, or version is unknown,
output
INSUFFICIENT CONTEXT: <field> and stop.
- Confirm
gh auth status shows repo + workflow scopes.
- Confirm the repo name equals the skill frontmatter
name
(grep '^name:' <skilldir>/SKILL.md). Fix the mismatch before continuing.
- Stage a clean copy into a build dir whose basename equals the skill name:
cp -R <skilldir>/. <stage>/ then delete __pycache__ and caches.
- Add
license: Apache-2.0 and version: <version> to the staged
SKILL.md frontmatter if absent.
- Fetch the Apache 2.0 text into
LICENSE:
curl -fsSL https://www.apache.org/licenses/LICENSE-2.0.txt -o LICENSE.
- Write
README.md, NOTICE, CONTRIBUTING.md, CODE_OF_CONDUCT.md,
SECURITY.md, .gitignore from the recipes in the reference.
- Write
.github/workflows/ci.yml that runs the skill's validators on
Python 3.9/3.11/3.12 plus a ruff lint job. Make frontmatter-check
CI-portable (it must pass with no Hermes installed).
- Write
.github/ISSUE_TEMPLATE/ forms and PULL_REQUEST_TEMPLATE.md.
- Run the local validator pipeline in the stage and fix every failure.
git init -b main, commit, and gh repo create <name> --public --source . --remote origin --push.
- Set repo topics and disable the wiki via
gh repo edit.
- Watch CI to green:
gh run watch <id> --exit-status. Do not proceed until
green.
- Apply branch protection with the 4 required checks
(
assets/branch-protection.json) via
gh api -X PUT repos/<owner>/<name>/branches/main/protection.
- Tag and publish the release:
gh release create v<version> --title v<version> --notes "...".
- Stage a fresh
git archive HEAD export (no .git), then run the
quarantine reinstall script in assets/reinstall-from-github.py with the
Hermes venv Python.
- Require the install scan verdict
safe (or caution allowed) and
should_allow_install == True; if blocked, sanitize per the reference and
repeat from step 11.
- Run the full Validation pipeline below and fix every failure before
returning.
Validation pipeline
- Frontmatter:
python3 scripts/check-skill-frontmatter.py
- Readability:
python3 scripts/check-dumb-model-readability.py SKILL.md
- No dead links:
python3 scripts/check-no-dead-links.py
- Determinism:
python3 scripts/check-determinism.py
- Workflow coverage:
python3 scripts/check-workflow-coverage.py
- Hermes security scan: with the venv Python, import
tools.skills_guard.scan_skill (source agent-created) and require
tools.skills_guard.should_allow_install(result) returns True.
- GitHub state:
gh api repos/<owner>/<name>/branches/main shows
protected: true; gh release view v<version> exists; CI is green.
Output template
Repo: https://github.com/<owner>/<name>
Skill name == repo name: YES
Version: <version> | Release: v<version> published
CI: green (Python 3.9/3.11/3.12 + ruff)
Branch protection: <N> required checks, strict, PR review, linear history
Reinstall: <safe|caution-allowed>, hub lock commit=<sha10> version=<version>
config.yaml hand-edited: NO
INSUFFICIENT CONTEXT escape hatch
If any of these are unknown, emit INSUFFICIENT CONTEXT: <field> and stop:
the skill directory path, the GitHub owner/org, the repo name (= skill name),
or the version string. Do not invent an owner or guess a version.
Critical-rule placement note
These critical rules are intentionally front-loaded at the top of this file and
book-ended: the final self-check below repeats the load-bearing ones so a weak
model re-reads them before finishing.
Verification checklist