Freshness Sidecar
Give Hermes local-file notes that warn the agent when their source files change.
An agent can remember “the API uses port 8000” long after the configuration changes. Freshness Sidecar binds that note to a file fingerprint and checks it again before each user turn.
It works alongside your existing memory provider. It does not occupy the memory-provider slot.
How it works
/fresh add file fact
|
v
Profile-local SQLite: note + path + fixed SHA-256 baseline
|
v
Next user turn: re-hash registered files
|
v
Status snapshot + up to 3 relevant FRESH facts -> Hermes model
The plugin makes no additional model calls.
Install
Requires Hermes 0.23.0 or newer.
hermes plugins install neweraXX/freshness-sidecar --enable
Notes live in the session's workspace: the working directory Hermes records for the session (for the CLI and messaging gateways this is terminal.cwd in config.yaml, the same directory the agent's own file tools use). Paths refer to the filesystem where Hermes runs; for Docker, mount the workspace into that container.
Usage
/fresh add app-config.json "API port is 8000"
/fresh add "docs/deployment guide.md" "Deployments use the staging cluster"
/fresh list
/fresh check
/fresh check 1
/fresh forget 1
Relative paths resolve against the session workspace. Notes are scoped to that canonical workspace and Hermes profile; a different workspace (including a subdirectory) sees a different set of notes. Symlinks, files outside the workspace and credential-looking files (.env, keys, credentials.json, ~/.ssh, ...) are refused.
list and check read the current file state. They do not update the saved baseline.
Adding the same file and fact again is idempotent. It does not silently accept a changed source as the new baseline. To replace a note, forget it and add the revised fact after reading the source again.
Model tool
The freshness_note tool exposes the same operations:
{"action": "add", "source_path": "app-config.json", "fact": "API port is 8000"}
{"action": "list"}
{"action": "check", "note_id": 1}
{"action": "forget", "note_id": 1}
Hermes Tool Search may defer this tool behind its discovery/call bridge. Use /fresh for direct control without relying on model tool discovery.
Status meanings
| Status | Meaning |
| --- | --- |
| FRESH | Current file bytes match the saved baseline. |
| STALE | File bytes differ from the saved baseline. |
| MISSING | The source file is no longer available at its path. |
| UNKNOWN | The plugin could not safely complete the check, for example because of permissions, a symlink or an oversized file. |
Changing a file and restoring its exact original bytes makes the note FRESH again.
FRESH does not prove the fact is true. It only establishes that the source bytes match those present when the note was saved.
Limits and semantics
- At most 20 active notes per workspace.
- Source files must be regular local files inside the workspace, at most 1 MiB.
- Note text is limited to 300 characters.
- Sources are checked before each user turn, not continuously or before every tool call.
- Up to 3 relevant FRESH facts are included, selected by path, filename and keyword matching.
- Each injected snapshot is bounded to 2,048 UTF-8 bytes. This is not an exact token limit.
- Status warnings take priority over fact bodies when space is limited; if even that does not fit, every note is still listed as
#id=STATUS. - A STALE/MISSING/UNKNOWN warning quotes the old claim (shortened) labelled
OUTDATED, because earlier answers based on it may still be in the conversation. - No automatic fact extraction, remote-source fetching, embeddings or background file watcher.
Hermes can persist injected context and replay it in conversation history. A FRESH snapshot from an earlier turn may remain visible to the model. New snapshots supersede earlier ones; the plugin does not rewrite history or erase information from other memory systems.
forget removes the active note and leaves a small tombstone, so later snapshots tell the model to ignore earlier blocks about that note id. It does not erase copies already in conversation history, exports or model-provider retention. Freshness warnings guide the model; they are not an execution firewall.
Privacy and security disclosure
Reads explicitly registered local files within the configured workspace to compute bounded SHA-256 checks. Stores note text, paths and hashes in profile-scoped plugin data. Selected notes and status snapshots reach the configured model and may persist in Hermes history. Forgetting stops future recall; it does not erase historical copies. FRESH means matching bytes, not verified truth. No direct network calls, subprocesses, background service, credential access or self-update.
Raw source-file contents are not stored by the plugin. Notes are not encrypted or isolated per chat user within the same profile/workspace. Use separate profiles for separate trust boundaries, and do not put secrets in note text.
Development and tests
Everything runs inside the official Hermes image, offline and non-root. From the repository root:
# unit tests (stdlib unittest, no Hermes imports, temp SQLite)
docker run --rm --network none --user 10001:10001 -e HOME=/tmp/h -e PYTHONPATH=/tmp/t \
-v "$PWD":/src:ro --entrypoint sh nousresearch/hermes-agent:latest \
-c 'mkdir -p /tmp/t && cp -r /src /tmp/t/freshness_sidecar && cd /tmp/t && python3 -m unittest discover -s freshness_sidecar/tests'
# end-to-end: real Hermes + local stub model, one session over 7 turns
mkdir -p e2e/out
docker run --rm --network none --user 10001:10001 -e HOME=/tmp/h -e HERMES_HOME=/tmp/h/.hermes \
-v "$PWD":/plugin:ro -v "$PWD/e2e/out":/out --entrypoint sh nousresearch/hermes-agent:latest /plugin/e2e/run_e2e.sh
# catalog checks
docker run --rm --network none --user 10001:10001 -e HOME=/tmp/h -e HERMES_HOME=/tmp/h/.hermes \
-v "$PWD":/plugin:ro --entrypoint hermes nousresearch/hermes-agent:latest plugins validate /plugin
The E2E script drives hermes chat --resume through: save via Tool Search tool_call -> FRESH -> unrelated question (status only) -> file edited (STALE) -> file deleted (MISSING) -> original bytes restored (FRESH) -> /fresh list, and asserts on the exact requests Hermes sent to the model (e2e/check.py), including that older FRESH blocks are replayed in history and superseded.
License
MIT.
README from the reviewed commit fbcb965; it updates when the author re-pins.

neweraXX