Skip to content

feat(sync): add hermes sync for profile backup to a personal git repo - #39343

Closed
kshitijk4poor wants to merge 1 commit into
NousResearch:mainfrom
kshitijk4poor:feat/profile-sync-git
Closed

feat(sync): add hermes sync for profile backup to a personal git repo#39343
kshitijk4poor wants to merge 1 commit into
NousResearch:mainfrom
kshitijk4poor:feat/profile-sync-git

Conversation

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Summary

Adds hermes sync — a CLI subcommand that lets independent users back up and sync their Hermes profile (skills, memory, persona, and a safe slice of config) to a git repository they control. Plain git under the hood, the user's own repo, no external service involved. This is the self-hosted / independent path: your data, your remote, zero dependency on any hosted backend.

It is distinct from the existing skills_hub (which installs skills from public GitHub repos) and skills_sync (which seeds bundled skills). Neither does bidirectional personal-profile sync; this fills that gap.

Commands

  • hermes sync init — set up sync. Prompts private or public (defaults to private for safety). Uses gh repo create when available, otherwise prompts for an existing remote URL. Writes a secret-excluding .gitignore and records the remote + visibility under a sync: key in config.yaml.
  • hermes sync push — stage the curated subset, run a pre-push secret scan, commit, and push. Aborts with a per-file report if anything secret-shaped is about to be committed.
  • hermes sync pull — fetch and restore into the live profile. Last-writer-wins; confirms before overwriting locally-modified files unless --force.
  • hermes sync status — remote, visibility, last sync time, pending changes, ahead/behind.
  • hermes sync share <skill> — print the exact install command others run (mirrors the skills_hub install format). Warns when the repo is private.

What syncs (and what never does)

Synced: skills/, memories/MEMORY.md, memories/USER.md, persona (SOUL.md), and an allow-listed config slice (display.skin, default_toolsets) materialized into a generated sync-config.yaml.

Never synced (.gitignore + a generated-config indirection so the raw file is never staged): .env, auth.json, the raw config.yaml (model/provider keys), state.db*, sessions.db*, logs, caches, heapdumps, checkpoints, plugin runtime data, *.pem/*.key.

Safety: pre-push secret scan

The push path reuses the existing tools/skills_guard.py scanner (scan_file + its credential-exposure pattern table) rather than introducing new regexes. The gate is restricted to credential-leak pattern ids (hardcoded secrets, private keys, GitHub/OpenAI/Anthropic/AWS keys). If a staged file trips one, the push aborts. Verified live: a planted AWS + Anthropic key blocks the push; a normal skill file passes.

Design notes

  • Dedicated staging git dir (<hermes_home>/.sync-git) that physically contains only the curated subset — chosen over a worktree over the live profile so it is structurally impossible to commit secrets that live elsewhere in ~/.hermes.
  • Profile-aware paths via get_hermes_home(); no hardcoded ~/.hermes.
  • Plain git via subprocess; no new dependencies.
  • Independent-git only — no hosted-backend / object-store layer.

Tests

tests/hermes_cli/test_sync_cmd.py — 17 tests covering secret exclusion, allow-listed-config enforcement, private-by-default init, and status output. All pass; neighboring CLI tests unaffected.

Test plan

  • pytest tests/hermes_cli/test_sync_cmd.py — 17/17 pass
  • Live end-to-end against a local bare repo: init → push (only allow-listed config landed; model.api_key did not) → secret-abort path → pull into a fresh profile → share
  • hermes sync --help registers all five subcommands

@kshitijk4poor
kshitijk4poor force-pushed the feat/profile-sync-git branch from e04fa8e to 1bc86bf Compare June 4, 2026 22:41
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard tool/skills Skills system (list, view, manage) labels Jun 4, 2026
@kshitijk4poor
kshitijk4poor force-pushed the feat/profile-sync-git branch 6 times, most recently from f675c8d to 386f341 Compare June 6, 2026 07:36
Adds a new `hermes sync` subcommand that lets independent git users back up
and sync a curated subset of their ~/.hermes profile to a git repository they
control. Plain git over subprocess; no Nous portal / object store.

Subcommands:
  - init   choose PRIVATE (default) or PUBLIC, create via gh or paste a remote,
           write a secret-excluding .gitignore, persist under config.yaml sync:
  - push   stage the synced subset, run a pre-push secret scan (reusing the
           credential-exposure patterns from tools/skills_guard.py) and ABORT
           if anything secret-shaped would be committed, then commit + push
  - pull   fetch + reset the staging mirror, restore into the live profile
           (last-writer-wins; confirms before clobbering unless --force)
  - status remote + visibility, last sync, pending changes
  - share  print the `npx skills add <url> --skill <name>` install command
           (mirroring tools/skills_hub.py); optional --push for one skill

What syncs: skills/ tree, memories/MEMORY.md, memories/USER.md, SOUL.md, and
an allow-listed slice of config (display.skin, default_toolsets) materialized
as a generated sync-config.yaml. The raw config.yaml is never synced.

Uses a dedicated staging git dir (<hermes_home>/.sync-git) that mirrors only
the curated subset, so it is structurally impossible to commit secrets living
elsewhere in the profile. Profile-aware via get_hermes_home(); no new deps.
@kshitijk4poor
kshitijk4poor force-pushed the feat/profile-sync-git branch from 386f341 to d0e969b Compare June 6, 2026 08:15
@teknium1 teknium1 added the area/profiles Multi-profile isolation, HERMES_HOME scoping label Jul 19, 2026
benbarclay added a commit that referenced this pull request Jul 28, 2026
…SP naming

Encapsulates the feature behind one command for launch, and adopts the
official product name.

One command:
- `propose` moves from `hermes skills propose` to `hermes sync propose`, so
  the whole feature is one command to learn and one to document. Its handler
  moves from cmd_skills to cmd_sync accordingly.
- The `hermes sync` parser now documents both halves plainly: personal sync
  across your devices, and sharing with your organisation. Added an examples
  epilog; rewrote the verb help in user language ("Include a skill in your
  sync" rather than "Opt a skill into sync").
- Every user-facing string that pointed at `hermes skills propose` now points
  at `hermes sync propose` (8 sites, including the agent-visible guidance
  returned by skill_manage and the org provenance header).

This also clears the way for #39343, which adds its own top-level `sync` for
git-repo profile backup — that feature nests under `skills`, this one owns
`sync`.

Naming:
- HSP / "Hermes Sync Protocol" is gone from prose, docstrings, and comments.
  The feature is "Skill Sync".
- Public identifiers renamed: HSPClient -> SyncClient, HSPError -> SyncError,
  HSPConflict -> SyncConflict, hsp_address -> wire_address, HSP_VERSION ->
  WIRE_VERSION.
- The WIRE names are deliberately NOT renamed: the `hsp_version` capability
  field and the `x-hsp-object-type` response header are set by the deployed
  gateway-gateway sync plane (verified in src/sync/syncRouter.ts), so
  renaming them client-side would break sync against a live server. A comment
  at the version constant records why they differ from the product name.
- The version-mismatch error is now actionable ("this server speaks sync
  version X, but this Hermes speaks Y — update Hermes to sync with it")
  instead of leaking the protocol acronym.

Also fixes a wiring gap found on the way: the gateway housekeeping tick
pulled personal skills but never org skills — the same defect already fixed
for the CLI. Org pull now runs there too, gated on real org membership.

Tests: the jargon guard now also fails on a bare "HSP". The two tests that
asserted the old cross-command structure are replaced by three asserting the
new one (propose IS under sync, propose is NOT under skills, sync usage
lists it). 2294 passed / 0 failed across all 51 suites that import the
changed modules, via scripts/run_tests.sh.

Verified by running the real CLI: `hermes sync --help` lists all eight verbs,
`hermes skills --help` no longer mentions propose, `hermes sync propose
--help` parses, and `hermes sync status` still reports live org state.
@kshitijk4poor
kshitijk4poor deleted the feat/profile-sync-git branch August 5, 2026 07:07
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…SP naming

Encapsulates the feature behind one command for launch, and adopts the
official product name.

One command:
- `propose` moves from `hermes skills propose` to `hermes sync propose`, so
  the whole feature is one command to learn and one to document. Its handler
  moves from cmd_skills to cmd_sync accordingly.
- The `hermes sync` parser now documents both halves plainly: personal sync
  across your devices, and sharing with your organisation. Added an examples
  epilog; rewrote the verb help in user language ("Include a skill in your
  sync" rather than "Opt a skill into sync").
- Every user-facing string that pointed at `hermes skills propose` now points
  at `hermes sync propose` (8 sites, including the agent-visible guidance
  returned by skill_manage and the org provenance header).

This also clears the way for NousResearch#39343, which adds its own top-level `sync` for
git-repo profile backup — that feature nests under `skills`, this one owns
`sync`.

Naming:
- HSP / "Hermes Sync Protocol" is gone from prose, docstrings, and comments.
  The feature is "Skill Sync".
- Public identifiers renamed: HSPClient -> SyncClient, HSPError -> SyncError,
  HSPConflict -> SyncConflict, hsp_address -> wire_address, HSP_VERSION ->
  WIRE_VERSION.
- The WIRE names are deliberately NOT renamed: the `hsp_version` capability
  field and the `x-hsp-object-type` response header are set by the deployed
  gateway-gateway sync plane (verified in src/sync/syncRouter.ts), so
  renaming them client-side would break sync against a live server. A comment
  at the version constant records why they differ from the product name.
- The version-mismatch error is now actionable ("this server speaks sync
  version X, but this Hermes speaks Y — update Hermes to sync with it")
  instead of leaking the protocol acronym.

Also fixes a wiring gap found on the way: the gateway housekeeping tick
pulled personal skills but never org skills — the same defect already fixed
for the CLI. Org pull now runs there too, gated on real org membership.

Tests: the jargon guard now also fails on a bare "HSP". The two tests that
asserted the old cross-command structure are replaced by three asserting the
new one (propose IS under sync, propose is NOT under skills, sync usage
lists it). 2294 passed / 0 failed across all 51 suites that import the
changed modules, via scripts/run_tests.sh.

Verified by running the real CLI: `hermes sync --help` lists all eight verbs,
`hermes skills --help` no longer mentions propose, `hermes sync propose
--help` parses, and `hermes sync status` still reports live org state.
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
…SP naming

Encapsulates the feature behind one command for launch, and adopts the
official product name.

One command:
- `propose` moves from `hermes skills propose` to `hermes sync propose`, so
  the whole feature is one command to learn and one to document. Its handler
  moves from cmd_skills to cmd_sync accordingly.
- The `hermes sync` parser now documents both halves plainly: personal sync
  across your devices, and sharing with your organisation. Added an examples
  epilog; rewrote the verb help in user language ("Include a skill in your
  sync" rather than "Opt a skill into sync").
- Every user-facing string that pointed at `hermes skills propose` now points
  at `hermes sync propose` (8 sites, including the agent-visible guidance
  returned by skill_manage and the org provenance header).

This also clears the way for NousResearch#39343, which adds its own top-level `sync` for
git-repo profile backup — that feature nests under `skills`, this one owns
`sync`.

Naming:
- HSP / "Hermes Sync Protocol" is gone from prose, docstrings, and comments.
  The feature is "Skill Sync".
- Public identifiers renamed: HSPClient -> SyncClient, HSPError -> SyncError,
  HSPConflict -> SyncConflict, hsp_address -> wire_address, HSP_VERSION ->
  WIRE_VERSION.
- The WIRE names are deliberately NOT renamed: the `hsp_version` capability
  field and the `x-hsp-object-type` response header are set by the deployed
  gateway-gateway sync plane (verified in src/sync/syncRouter.ts), so
  renaming them client-side would break sync against a live server. A comment
  at the version constant records why they differ from the product name.
- The version-mismatch error is now actionable ("this server speaks sync
  version X, but this Hermes speaks Y — update Hermes to sync with it")
  instead of leaking the protocol acronym.

Also fixes a wiring gap found on the way: the gateway housekeeping tick
pulled personal skills but never org skills — the same defect already fixed
for the CLI. Org pull now runs there too, gated on real org membership.

Tests: the jargon guard now also fails on a bare "HSP". The two tests that
asserted the old cross-command structure are replaced by three asserting the
new one (propose IS under sync, propose is NOT under skills, sync usage
lists it). 2294 passed / 0 failed across all 51 suites that import the
changed modules, via scripts/run_tests.sh.

Verified by running the real CLI: `hermes sync --help` lists all eight verbs,
`hermes skills --help` no longer mentions propose, `hermes sync propose
--help` parses, and `hermes sync status` still reports live org state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have tool/skills Skills system (list, view, manage) type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants