Repository navigation
Description
Summary
The skills system currently exposes several independent concepts through overlapping labels:
- physical/effective location — profile-local,
skills.create_dir,skills.external_dirs, trusted project, plugin; - distribution origin / updater — bundled, Hub/URL, external upstream, user-authored, agent-authored;
- write policy — foreground
skill_manage, background review, Curator lifecycle; - Curator opt-in state — the
.usage.jsoncreated_by: agentmarker; - scope — skill content may be shared while usage/ownership state remains profile-local.
The documentation describes pieces of this model, but not as one contract, and the CLI collapses several categories. An operator cannot reliably answer “which copy is active, who can modify it, and who will update it?” without reading the implementation.
This was encountered while configuring the same agent-authored library across seven profiles while preserving bundled/Hub update ownership. The reproductions below use a fresh synthetic HERMES_HOME against current main (5dea46d13deec9549bdc2ea703ae9201d733c28d); they do not depend on that real installation.
This is not another request for a global skill store. It is a documentation + observability request for the behavior Hermes already exposes.
Where the documentation and surfaces diverge
1. The opening mental model is already false for supported roots
The Skills page says that “All skills live in ~/.hermes/skills/ — the primary directory and source of truth”:
The same page later documents create_dir, external_dirs, and trusted project roots, while profiles use their own HERMES_HOME. “All skills” and a single “source of truth” therefore do not describe the supported resolution model.
2. external_dirs are called both read-only and mutable
The shipped config example says:
External dirs are read-only
The user guide says existing external skills are updated in place and that external dirs are not a write-protection boundary:
Current implementation has a third, contextual rule: external/project roots are read-only to autonomous lifecycle maintenance, while user-directed tool calls may still edit them:
So “read-only” is not a property of the directory alone; it currently depends on the write origin. PR #108040 may change the foreground default, which makes it even more important for the docs and config example to state the same final contract.
3. create_dir is documented as fully integrated, but is not
The guide recommends create_dir for a shared “brain” / fleet-wide volume and says its skills appear in the prompt index, skills_list, skill_view, and slash commands:
On current main, a clean repro produces:
skill_manage create : true
in prompt index : true
skills_list names : []
skill_view : Skill 'create-dir-audit-demo' not found.
The implementation has a canonical get_all_skills_dirs() containing local → create_dir → external:
but the list/view path rebuilds roots as project + local + external and omits create_dir:
This specific functional bug is already tracked by #108157. I am including it here only because the current documentation presents the broken path as the recommended no-hacks solution for shared creation.
4. hermes skills list cannot reveal the effective storage/ownership model
The installed-skills command accepts only all | hub | builtin | local:
and classifies every non-Hub, non-bundled skill as local, regardless of whether the winning file is in an external or project root:
Synthetic current-main output with one local skill, one external skill, and one create_dir skill:
Installed Skills
Name Source Trust
external-audit-demo local local
local-audit-demo local local
0 hub-installed, 0 builtin, 2 local
The external skill is labeled local; the create_dir skill is absent because of #108157. There is no path or update-owner field with which to disambiguate them.
5. “agent-created” is still used as an operator-facing synonym for Curator-managed
The Curator guide eventually explains the actual contract correctly:
created_byis a policy flag, not a provenance claim
The implementation says the same and shows that curator adopt writes created_by: agent to a user-authored skill:
That policy sidecar always lives under the active profile's get_hermes_home()/skills/.usage.json, not beside a shared create_dir artifact:
Yet the same guide section is titled “What agent-created means”, its sample status reports agent-created=..., and the real CLI still prints that counter:
That forces users to learn that “agent-created” sometimes means authorship and sometimes means “autonomous Curator writes are allowed.” Existing issue #70712 covers the Desktop “learned” badge; this issue asks that the docs and CLI stop overloading the same concept too.
Why this matters
This ambiguity affects safe operations rather than wording alone:
- an external/upstream-owned skill can be mistaken for a local owned copy;
- a user can assume “read-only” protects foreground writes when it currently does not;
- a user can assume an adopted skill was authored by the agent;
- a recommended
create_dirshared setup advertises skills the agent cannot subsequently load; - across profiles, shared content and profile-local lifecycle metadata can be mistaken for one shared management state.
The practical workaround is duplicate profile-local copies plus manual reconciliation—the opposite of the “shared brain” mental model suggested by the guide.
Requested outcome
Please define one canonical skills contract and expose it consistently. A matrix in the Skills page would be sufficient documentation-wise, with rows for:
- profile-local / bundled copy;
- Hub-installed;
skills.create_dir;skills.external_dirs;- trusted project skills;
- plugin-provided skills.
Suggested columns:
- resolution precedence and effective path;
- distribution origin / update owner;
- foreground
skill_managemutability; - background-review mutability;
- Curator lifecycle eligibility (
adopt, stale/archive, pin); - location/scope of
.usage.jsonstate; - whether
hermes updateor Hub update may overwrite the copy; - which discovery surfaces include the root.
For operator visibility, hermes skills list (including JSON output if added) should report separate concepts rather than one overloaded Source value—for example location_kind, origin/update_owner, and curator_managed—or at minimum show the resolved path and distinguish external, create_dir, and project from profile-local.
Acceptance criteria
-
skills.md,curator.md, andcli-config.yaml.exampledescribe the same external-dir mutability contract. - The opening Skills mental model covers profile-local,
create_dir, external, project, and plugin roots instead of saying all skills live in one directory. -
create_diris either integrated across every documented discovery surface (tracked by skills.create_dir skills are advertised in the prompt but skill_view / skills_list / slash commands can't find them #108157) or the docs stop claiming that it is. -
hermes skills listlets an operator identify the winning copy's location/update ownership; external skills are not reported only aslocal. - Curator output distinguishes authorship/provenance from the autonomous-management opt-in; an adopted skill is not described as agent-authored.
- Multi-profile docs state explicitly whether content, usage metadata, and Curator ownership are profile-local or shared.
- Contract tests cover every documented root across prompt index,
skills_list,skill_view, slash commands, and write/lifecycle guards.
Related, not duplicate
- skills.create_dir skills are advertised in the prompt but skill_view / skills_list / slash commands can't find them #108157 — functional
create_dirdiscovery bug. - [Bug/Security]: external_dirs skills misclassified as "learned" (agent-owned) with absent write/patch permission guard #108032 / PR fix(skills): classify external_dirs as external and default-deny in-place writes #108040 — external provenance and foreground write policy, primarily API/Desktop and mutation guarding.
- bug(desktop): local skills are mislabeled as learned regardless of origin #70712 — Desktop “learned” badge conflates local/unclassified with learned.
- Feature: make global skills truly global across profiles #19451 and [Feature]: Global, self-improving skills have no first-class home — and protecting them forces a DRY violation #34782 — first-class global/shared skill storage design.
Those issues each address one behavior or UI. This issue is for the missing cross-cutting documentation and operator-facing contract that ties storage, provenance/update ownership, mutability, Curator management, and profile scope together.
Activity
kokhlo commentedon Sep 13, 2026
Verified the report against current
main(5dea46d1) — all five divergence points hold by direct reading, and #110138 already covers the documentation half. Adding review context on what it does and doesn't close, since the acceptance criteria reach beyond the two edited files.Confirmed on main:
skills.mdL11 still opens with "All skills live in~/.hermes/skills/— the primary directory and source of truth" while the same page later documentscreate_dir,external_dirs, and trusted project roots.cli-config.yaml.exampleL1057 says external dirs are flatly "read-only", but the actual boundary is write-origin, not directory:tools/skill_manager_guards.pyL164-181 only refuses autonomous (background review) writes to external/project roots — user-directedskill_manageedits still land in place, asskills.mdalready says.hermes_cli/skills_hub.pyL790 classifies every non-Hub, non-bundled skill aslocalwith no path/origin column, sohermes skills listcannot distinguish an external root orcreate_dircopy from a profile-local one.On #110138 (docs-only:
skills.md+curator.md):get_all_skills_dirs()(agent/skill_utils.pyL398-406) resolves local →create_dir→ external, trusted project roots sit above that chain (L399-400 docstring, L409-413 comment), and the write-policy split matches_background_review_write_guard.config_defaults.py— the previous 30d/90d text was stale either way.Still open per the acceptance criteria, not covered by that PR:
cli-config.yaml.exampleL1055-1059 still calls external dirs "read-only" with no write-origin qualifier — AC Terminal tool #1 names this file explicitly.hermes skills liststill reports one overloadedSourcevalue (skills_hub.pyL781-805; choices insubcommands/skills.pyL70) — AC Fix terminal interactivity #4 needslocation_kind/resolved-path level reporting.hermes curator statusstill printsagent-created=Nfor what is a management opt-in (hermes_cli/curator.pyL117-119) — AC Update snapshot #5.Compose note: #108040 (open) proposes default-denying in-place writes to external dirs. #110138's contract text describes today's behavior ("user-directed ... update ... in place"), which is correct for current main — but if #108040 lands, that sentence and the config example should flip together, so the two PRs share one sentence whichever order they merge in.
Items 2 and 3 look like small, well-scoped follow-ups to split from the docs PR if maintainers prefer — happy to take either or review.