Skip to main content

Skill Updater

Update third-party imported agent skills and report changes. Maintains the third-party skills imported from upstream GitHub repos into this profile's skill directory.

Layout​

  • /home/xisroot/skill-upstream/ - shallow staging clones of every upstream repo that supplies imported skills.
  • /home/xisroot/skill-upstream/manifest.json - provenance: one entry per installed skill with repo, src_path, upstream_commit, repo_url. Single source of truth for the updater.
  • /home/xisroot/skill-upstream/update.py - the updater. Deterministic stdout (no timestamps) so the cron monitor can diff it.
  • ~/.hermes/skills/.quarantine/ - hidden dir; anything here is NOT scanned by the skill loader.
  • Daily cron job skill-updates (cronjob_manage list to find job_id) runs update.py via its monitor; the agent only wakes when output changes, then reports to the origin chat.

What update.py does, in order​

  1. git fetch --depth 1 each staging clone; if upstream moved since the recorded commit, git reset --hard FETCH_HEAD.
  2. For each skill whose repo moved: tree-hash upstream source vs installed copy. Changed + scanner clean -> overwrite installed copy byte-identical. Changed + scanner hit -> copy new tree to .quarantine/<skill> and leave the old installed copy untouched.
  3. Run shared-skills-sync/scripts/sync.py publish (idempotent, refuses conflicts), commit + push hermes-sparke1b8 only when publish wrote files.
  4. Print deterministic report: REPOS_CHANGED / SKILLS_UPDATED / SKILLS_UNCHANGED / QUARANTINED / ERRORS / RESULT.

Safety scanner rules (keep in lockstep in update.py and any import script)​

Hard blocks (quarantine): pipe-to-shell (curl|sh variants), /dev/tcp/, netcat exec, base64-pipe-shell, .onion addresses, rm -rf /|~|$HOME, eval $(curl). Warn-only: telemetry/analytics mentions (manual review).

Adding a new upstream repo​

  1. git clone --depth 1 https://github.com/<owner>/<name> /home/xisroot/skill-upstream/<unique-dir> - use unique dir names when repo names collide.
  2. Pick the canonical non-hidden SKILL.md source dirs (hidden dirs like .claude/, .openclaw/ are skipped by the Hermes skill scanner anyway; prefer skills/ or the repo's primary skill tree).
  3. Safety-scan, copy into ~/.hermes/skills/<category>/<skill>/ byte-identical, check frontmatter (name + description required).
  4. Append manifest entries (skill, repo, src_path, upstream_commit, repo_url, imported_at).
  5. Run python3 /home/xisroot/skill-upstream/update.py once to confirm "RESULT: nothing changed".

Peer-branch pull pipeline (skill-pull)​

~/.hermes/scripts/skill_pull.py + cron job skill-pull (daily 6:15am, after skill-updates). Scans every other hermes-* branch in the shared repo via git ls-remote + fetch to refs/remotes/origin/<branch>. For each skill NAME this profile doesn't have (never overwrites): git archive origin/<branch> skills/<cat>/<name> (note: archive emits the FULL tree path, so locate the SKILL.md dir by walking the extraction), run the same BLOCK_RE scanner, clean -> ~/.hermes/skills/<their-category>/<name>, hit -> .quarantine/pull/<branch>/.... Divergent content on multiple branches: alphabetically first branch wins, conflict reported. Anything pulled is shared back via sync.py publish + commit + push to hermes-sparke1b8. Re-running is idempotent (re-copying an existing quarantine item is safe).

Pitfalls​

  • NEVER edit imported skill content locally - updates are byte-identical overwrites, and local edits silently vanish on the next update. To customize, fork the skill into a new directory.
  • update.py and the import script both keep the BLOCK_RE lists - update BOTH when adding a pattern.
  • The Hermes skill scanner skips hidden dirs and treats references/ templates/ assets/ scripts/ as support files - target dirs must respect that or the skill won't load.
  • Git push auth: repo-local credential.helper store with ~/.git-credentials (0600). No token in env or history.
  • Colliding skill names: keep the older/better copy and skip the import (the plan script checks against existing skills before copying).
  • Superpowers telemetry: the repo ships with telemetry on; keep it disabled if hooks are ever installed locally.
  • sync.py publish discovers skills with rglob("SKILL.md") which does NOT skip hidden dirs — it was fixed to exclude dot-prefixed path parts (regression test test_inventory_hidden_skill_dirs_are_never_published). Any tool that inventories the profile dir must keep skipping .quarantine and other hidden trees, and sync.py does not delete stale remote files (no prune) — remove accidental publishes with git rm + push.
  • Cron jobs snapshot the provider at creation time: if the profile's default provider is later changed (e.g. to a named custom provider), existing jobs keep the stale bare custom value and die with "No LLM provider configured". Fix: hermes cron edit <id> --provider <current>. Verify the provider field in the job's config before relying on a job.
  • Pull output determinism: the quarantine list appears in stdout; that's stable (same skill quarantined every tick = same output = agent suppressed). Only NEW quarantines or pulls wake the agent.

Source: jknash/hermes-shared-skills · branch hermes-jkdev001 @ 1d0d545c3970 · skills/skill-updater/ · view source · Imported 2026-10-04. Supporting files (references, scripts) remain in the source repository.

version 1.0.0 · author Justin Knash (jknash), Hermes Agent · license MIT.

Published by Muse · 2026-10-04.