Skip to content

materialize: first-class hermes harness (global ~/.hermes/skills/spindle target)#1

Open
lavallee wants to merge 3 commits into
mainfrom
feat/hermes-harness
Open

materialize: first-class hermes harness (global ~/.hermes/skills/spindle target)#1
lavallee wants to merge 3 commits into
mainfrom
feat/hermes-harness

Conversation

@lavallee

@lavallee lavallee commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What

spindle bind <repo> --harness hermes now materializes into the global Hermes skills tree instead of a repo-local directory hermes never reads.

Why

Hermes discovers skills exclusively by recursively walking ~/.hermes/skills/ (os.walk(..., followlinks=True) over SKILL.md index files, pruning only VCS/venv/cache dirs — no hardcoded category list). It does not look at repo-local .hermes/skills, so the generic .{harness}/skills fallback in materialize.target_dir produced dead symlinks from hermes's point of view.

How

  • paths.hermes_skills_dir()~/.hermes/skills/spindle/ by default, overridable via SPINDLE_HERMES_SKILLS_DIR. A dedicated category dir so spindle never touches hand-curated hermes categories.
  • materialize.GLOBAL_HARNESS_DIR — explicit mapping (not the fallback) for harnesses whose discovery is global-only; target_dir consults it first. The repo argument still names the binding surface; only the materialization target is global.
  • Everything else flows through unchanged: symlinks named after the skill, reconcile-against-previous-binding, dry-run, unbind removing only spindle-owned links.

Verified

  • Unit + binder-level tests: link/keep/remove cycle in the dedicated category, foreign dirs untouched, dry-run writes nothing, env override honored, end-to-end bind→record→unbind for a hermes surface. Suite: 605 passed (was 598).
  • Manual CLI smoke test against the sample distribution with a hermes channel manifest: bind → 4 links in the category dir, re-bind → all kept at the same coordinate, unbind → all removed, dir left empty.

Caveats

  • One shared target dir means hermes-bound surfaces share a skill namespace there (documented in README).
  • No hermes dialect profile yet — skills land in claude-reference dialect; rendering/profile transform for hermes is future work (tracked in the forge plan).

🤖 Generated with Claude Code

lavallee and others added 3 commits July 7, 2026 05:01
Hermes discovers skills only by recursively walking ~/.hermes/skills
(followlinks=True) — it never reads repo-local .hermes/skills, so the
generic ".{harness}/skills" fallback produced a directory hermes would
never see. Bindings for --harness hermes now materialize into a
dedicated, spindle-owned category dir ~/.hermes/skills/spindle/
(overridable via SPINDLE_HERMES_SKILLS_DIR) so hand-curated hermes
categories are never touched. The repo argument still names the binding
surface; only the target dir is global. Symlink + reconcile-against-
previous-binding semantics are unchanged, so bind/unbind/dry-run flow
through identically.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Covers: links created under the dedicated category dir (and nothing
inside the repo), re-bind keeps, unbind removes only spindle-owned
symlinks while foreign dirs in the category survive, dry-run writes
nothing, SPINDLE_HERMES_SKILLS_DIR override honored, and a binder-level
end-to-end bind→record→unbind cycle for a hermes surface.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Documents the per-harness materialization targets, the global hermes
target with its env override, the shared-namespace caveat, and that
skills land in claude-reference dialect for now — hermes dialect
rendering/profile transforms are future work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant