0.3.0 reduced core. Qualified on the exact Linux/Hermes/Node/engine/model tuple in validation, with a mandatory stationary-vault restriction. This is not the historical full-feature release. Publication is a separate remote-readback gate; resolve the published tag before installation. Production deployment and service changes were not made. Contract, release notes and upgrade restrictions define the active scope. Earlier candidate documents are preserved under
docs/history/, not active installation or recovery instructions.
A local-first Hermes Agent
memory provider backed by zvec-grep.
Markdown facts and session notes are the source of truth; zg supplies hybrid
BM25/vector retrieval with cited file locations. Built-in MEMORY.md/USER.md
remain separate and available.
- The one pinned Linux/Hermes source tuple bound by final release validation.
- Node.js 26.8.1 and
@zvec/zvec-grep@0.2.2. - Only
local/potion-retrieval-32m; model switching is refused. - POSIX filesystem locking. Other platforms and broader Node versions are not qualified by this reduced release.
- The vault and all ancestor directories must remain stationary while active.
Installing a plugin is not activating it. Only one external provider can be active per Hermes profile. Do not modify Hermes core to install this provider.
Publication is not production deployment. Use an approved maintenance window;
never replace plugin code while any process owns the vault. Managed setup is
supported only for the default ~/.hermes profile.
From a Git checkout with the verified v0.3.0 tag, resolve its exact commit and
install through the host manager (not a live directory copy):
RELEASE_SHA="$(git rev-list -n1 v0.3.0)"
hermes plugins install 'https://github.com/r0b0tlab/hermes-zvec-memory#zvec-memory' --ref "$RELEASE_SHA"
hermes memory setup zvec-memory
hermes zvec-memory status --json
hermes zvec-memory doctor --jsonThe qualified setup prerequisite is an already provisioned, exact
@zvec/zvec-grep@0.2.2 runtime in a stable user-owned prefix and the cached
local/potion-retrieval-32m model. Setup verifies the real package/executable,
creates and reads back its launcher/unit/manifest, writes private canonical
JSON and publishes memory.provider. It does not fetch dependencies or start,
reload or restart a service. A fresh network/bootstrap install is not covered
by the isolated qualification. Never use a test checkout as a production SDK.
The explicit fetching command is hermes zvec-memory engine install; custom
provider CLI discovery requires the provider already be selected. Do not assume
this command is exposed before initial selection/setup. Existing-SDK engine
verification was exercised; a fresh npm download was not.
Start a fresh Hermes session after setup. The generated launcher can run the
local engine directly when no daemon is present. If a managed daemon is wanted,
loading/starting its unit is a separately authorized operator service action,
not something performed by this release. An unloaded service legitimately makes
doctor unhealthy; status is informational and returns 0. Neither result
certifies production service health. Reindex returns durable requested, not
completed intent; verify a later session consumes it and cites real sources.
The standalone scripts/upgrade.py is retired: all invocation forms return 2
without running subprocesses or changing files. Use the host plugin manager at
an exact approved revision. Automatic migration, provider backup/restore and
historical standalone rollback recipes are unsupported; see
upgrade restrictions.
Canonical file: $HERMES_HOME/zvec-memory/config.json.
{
"vault": "$HERMES_HOME/zvec-memory",
"zg_bin": "zg",
"embedding": "local/potion-retrieval-32m",
"recall_limit": 5,
"context_chars": 2000,
"preview": "short",
"auto_extract": false,
"reindex_min_seconds": 600,
"prefetch_cache_seconds": 120
}Omit vault for the profile-local default. Relative vault paths are resolved
against the active Hermes home; both $HERMES_HOME and ${HERMES_HOME} expand.
Only CLI setup is supported. Desktop/F9 configuration is not declared, and the
legacy generic configuration writer explicitly refuses before publication.
If JSON is absent, legacy plugins.zvec-memory in config.yaml is read without
modifying it. CLI setup preserves supported settings while writing JSON; there
is no automatic migration during provider startup. Once JSON exists it is
authoritative, even when empty. Malformed or unsupported selections refuse
instead of silently resetting user choices. migrate-config refuses with exit 2.
Use Hermes's config CLI for host settings such as memory.provider; never
hand-edit the host YAML as part of plugin installation.
recall_limit is bounded to 1–50. context_chars caps recall text including its
heading/truncation marker. preview is none, short, or full.
Changing embedding is unsupported in this release, including another local
model. Explicit null, empty, false, or remote selections also refuse. Omitting
the setting selects local/potion-retrieval-32m.
Model downloads require network; local retrieval itself needs no cloud account.
facts/: explicitly stored facts and tracked built-in memory mirrors.sessions/: daily text logs; each record captures its originating session ID before asynchronous work. User/assistant portions are truncated to 1500 characters each. This is not an archival transcript/checkpoint guarantee..mirror-map.jsonand.mirror-staging/: mirror ownership/recovery state; these are not recall documents. Indexing is restricted to Markdown in facts and sessions, not the provider's JSON configuration..mirror-inbox.sqlite3: durable FIFO for critical built-in notifications, using Python's stdlib SQLite. This is a delivery queue, not a replacement retrieval database. Pending notifications are replayed after restart..mirror.lock: POSIX transaction lock shared by separate Hermes processes..mirror-delivery-failed.json: fail-closed marker if notification persistence fails. Restore storage health and reconcile the built-in memories with their owned mirror records before removing this marker; do not blindly delete it to silence an error. Snapshot the inbox/map/facts together before repair..zvec-grep/: rebuildable native index.
Facts use exclusive private file creation instead of content-derived colliding
names. Symlinked writer directories are rejected. Explicit memory_store returns
stored only after the file write succeeds; index visibility is asynchronous.
Automatic persistence uses a bounded FIFO and logs rejected work or incomplete
shutdown rather than claiming it was flushed.
Built-in add/replace/remove notifications affect only mapped mirror-owned facts.
A recovery journal protects interrupted mirror publication/deletion; recall is
withheld while required native index cleanup remains incomplete. Ambiguous
legacy ownership is not guessed. Legacy mirror adoption is deferred;
migrate_legacy_mirrors(entries) explicitly refuses before vault access.
Removing a mirrored fact is NOT full erasure. Old text may remain in session history, backups, or snapshots. Do not promise a privacy deletion across those stores. Automatic preference extraction is off by default, uses only user messages, and refuses extraction if its compaction-safety filters are missing. Pre-compress behavior remains best-effort API v1, not a durable API v2 checkpoint.
The provider offers memory_search (hybrid, fts, vector, globs, limit) and
memory_store (content, category, tags). Queries are passed as explicit argv
values, including strings beginning with a dash; no shell evaluation is used.
Prefetch has a short timeout and fails open to no context; explicit tool errors
remain visible. Empty successful results are cached, errors are retried, and
writes/index changes invalidate stale prefetch results.
Index refresh is coalesced and debounced; failed runs retain dirty state. After bounded immediate contention retries, later automatic prefetch or explicit search reschedules dirty work with a one-second cooldown. Retry is demand-driven, not a persistent periodic timer, and is suppressed during shutdown. The first search following a write may not see it yet: wait for a successful refresh before asserting that new/deleted data is visible/absent. Native lock/lease contention is not success.
For lower warm-query latency, a local zg daemon keeps models loaded:
zg server on --listen 127.0.0.1:17999 --token-file /absolute/private/server.token
zg server status --check-readyCreate a private random token first and configure clients with the matching
ZVEC_GREP_SERVER_TOKEN_FILE. Use a dedicated ZVEC_GREP_HOME and loopback
address for isolation. An unauthenticated daemon is not the recommended default.
Supervise it with the OS user service manager for restart/login persistence.
Never start a second daemon on an occupied port or stop someone else's daemon.
Without a daemon, --refresh background falls back to no refresh in direct zg;
the provider's own index scheduling remains necessary.
hermes memory status
hermes zvec-memory doctor # exit 0 when healthy; --json for machines
zg status /absolute/vault --check-readyEveryday maintenance (install, upgrade, rollback, versioned formats, recorded
limits and troubleshooting) is documented in docs/maintenance.md.
In a fresh Hermes session, store a harmless fact and retrieve it by paraphrase,
checking the cited file content. Provider backup/restore is unsupported;
backup_paths() explicitly refuses without resolving or initializing a vault.
The host collector tolerates that refusal. This does not prevent the host's
generic profile archive from including profile-local files; such an archive is
not a qualified provider snapshot or restoration procedure.
Offline tests require a Hermes checkout on HERMES_AGENT_DIR and a separate
Python environment with the pinned test dependencies:
uv venv --python 3.11 .venv
uv pip install --python .venv/bin/python -r requirements-test.txt
HERMES_AGENT_DIR=/absolute/hermes-agent .venv/bin/python -m pytest tests/ -m 'not integration' -qNative tests require explicit opt-in and a reusable local model cache:
HERMES_AGENT_DIR=/absolute/hermes-agent \
ZVEC_RUN_NATIVE=1 \
ZVEC_TEST_BIN=/absolute/zg \
ZVEC_TEST_MODEL_CACHE=/absolute/test-model-cache \
.venv/bin/python -m pytest tests/test_zg_native.py tests/test_provider_native.py -qThese use synthetic data and temporary homes. Historical full-scope tests are preserved, including desktop/config, migration, backup, and model-switching oracles. They are not all applicable to this core. Final validation must list their explicit dispositions and execute the applicable core plus successor CLI/setup/refusal coverage; an excluded or unexecuted case is not PASS.
HERMES_AGENT_DIR=/absolute/hermes-agent .venv/bin/python scripts/measure_recall.py \
--zg-bin /absolute/zg --model-cache /absolute/test-model-cache \
--output benchmark-results/recall.jsonThe script seeds before initialization, records exact versions/SHAs, fails on native errors, and separately reports retrieved hit@5, visible hit@5, context size, repeated-identical-query cache latency, and distinct-next-turn latency. It cleans its temporary vault after workers stop. JSON output includes full synthetic query evidence and failures.
Hermes queues the just-completed query, not a predicted next query. A repeated cache hit is not evidence that all subsequent questions become faster. Initial same-hardware comparison retained 10/10 near-wording and 8/10 paraphrase hybrid recall in both baseline and hardened providers; no general speedup was shown. See review evidence for tested versions, limitations, and actual deployment/benchmark results rather than extrapolating old numbers.
MIT. Retrieval engine zvec-grep is Apache-2.0. This provider stays a standalone plugin and does not patch Hermes core.