neuralmind.uk / NeuralMind v4.23.1 — the Hermes plugin serves each session’s own project under Hermes 0.22’s gateway, and a first turn’s recap arrives within the timeout Edit this page on GitHub ↗

NeuralMind v4.23.1 — the Hermes plugin serves each session’s own project under Hermes 0.22’s gateway, and a first turn’s recap arrives within the timeout

Type: Patch release Theme: on Hermes 0.22.2 and later, CLI, TUI and Desktop sessions get their project’s context again, and on a large repository a session’s first turn gets the previous session’s recap

Since Hermes 0.22.2, the hooks of every local session (CLI, TUI and Desktop) run in one Hermes gateway process, not in the hermes command you start. That process’s own working directory and environment belong to no session. Hermes’s plugin guide says so, and gives plugins ctx.session_cwd() for the calling session’s working directory instead.

The NeuralMind plugin didn’t ask for it. Unpinned, it served the first built project among NEURALMIND_PROJECT, TERMINAL_CWD and the current directory, all read from the gateway’s own environment. On a 32-core Linux machine running Hermes 0.22.5, the gateway’s TERMINAL_CWD was the user’s home directory, which isn’t a built project. So every hermes chat turn in a built hermes-agent checkout got no NeuralMind context at all: no recall block, and no recap on a session’s first turn. The plugin also wrote nothing for the session and logged no warning. Setting NEURALMIND_PROJECT on the command didn’t help: the variable stayed in the client process.

The second fix is for a session’s first turn on a large repository. v4.23.0 made the per-prompt hook fast on a large index, so on hermes-agent the Hermes plugin got its block within the default 8 s: 2.5–3.9 s a turn on a 32-core Linux machine under load. A session’s first turn makes one more call: the plugin runs neuralmind _hook session-start for the previous session’s recap, as a separate process with its own 8 s limit (NEURALMIND_HERMES_TIMEOUT). That call still overran there. It took 6.3–7.7 s on a freshly rebuilt hermes-agent index (337,346 nodes, 1,272,023 synapse edges), and Hermes’s log said neuralmind _hook session-start took longer than 8.0s and was stopped.

The recap itself was quick. The hook wrote it first, then ran a synapse decay tick and the SYNAPSE_MEMORY.md export over the whole store: under a profiler those were about 6 s of the call (the export’s hub and strongest-pair queries 4.2 s, the decay tick 1.9 s). When the plugin stops a call, it drops everything the call wrote, so the recap was thrown away with the rest. The workaround was starting Hermes with NEURALMIND_SYNAPSE_EXPORT=0, which also stopped the export, and which, on Hermes 0.22.2 and later, never reached the hooks when set on the hermes command.


What changed

Under the gateway, the plugin follows the session’s working directory

NEURALMIND_PROJECT counts only where the hooks run

Under the gateway, setting NEURALMIND_PROJECT (or any NeuralMind switch, such as NEURALMIND_SYNAPSE_EXPORT) on the hermes command you start doesn’t reach the plugin. Only the gateway’s own environment does, and there it applies to every session, like a pin. The docs that said to set it for Desktop, ACP and per-session workspaces now say this instead.

On a large store, the decay tick and the export run after the hook returns

The size limit is on the file, which also holds the build’s structural tables (about 300 MB of hermes-agent’s store), so a store with few learned edges but a large code graph is maintained in the background too. That costs nothing but the few seconds before the file is rewritten. A store under 64 MB holds at most about 115,000 synapse edges; one that size took 0.44 s on an M3.


What the agent sees post-install

Agent Before v4.23.1 From v4.23.1
Hermes-Agent plugin, Hermes 0.22.2+, unpinned No NeuralMind block or recap in CLI, TUI and Desktop sessions, unless the gateway’s own TERMINAL_CWD or working directory was a built project, and then every session got that project’s Each session gets its own project’s block, and its recap on its first turn, when its working directory is built
Hermes-Agent plugin, any version, large store A session’s first turn could lose the recap: the session-start call was stopped at 8 s. NEURALMIND_SYNAPSE_EXPORT=0 avoided it, where it reached the hooks The recap arrives: the call returned in 0.18–0.62 s on an M3 and 2.0–3.6 s on the Linux machine, and the decay tick and export finish in the background
Hermes-Agent plugin, older Hermes or pinned Followed TERMINAL_CWD, or the pin Unchanged
Claude Code (SessionStart hook) Session start waited for the decay tick and the export (4–8 s on a 1.27M-edge store) before the first prompt Session start no longer waits for them. On a store of 64 MB or more, SYNAPSE_MEMORY.md is rewritten a few seconds after the hook returns, so a session may load the file the previous session start wrote
Cursor, Cline, generic MCP No SessionStart hook or Hermes plugin; unaffected Unchanged

Claude Code reads @.neuralmind/SYNAPSE_MEMORY.md through CLAUDE.md, and we haven’t checked whether it loads the file before or after its SessionStart hooks finish, so this release doesn’t claim that a session sees the export its own start writes, before or after the change.


Measured

Which project a Hermes session gets

Checked on one machine and one Hermes version, not benchmarked: a 32-core Linux laptop running Hermes 0.22.5, with the plugin installed unpinned. The session ran in a built clone of hermes-agent, and the model was a local gpt-oss:20b-64k served by Ollama.

  v4.23.0 plugin This change
NeuralMind hook processes a hermes chat turn started in its first 40 s 0 2: session-start at 2.6 s, prompt-submit at 10.6 s
A recap file for the session in the clone’s .neuralmind/recaps/ none written
The NeuralMind block in the user message Hermes sent the model absent (2 turns checked) present (1 full turn, 582 s on CPU)

A session’s first-turn recap

tests/benchmark/session_start_latency.py runs one fresh neuralmind _hook session-start process per sample, with a recap to return, and times it from start to exit, as the agent waits for it (hook). It also times from the same start until the store work is finished (done): when the detached process releases its lock, or, when there is none, when the hook exits. 5 samples each, on an M3 MacBook (8 cores), once idle and once with six busy loops running (yes > /dev/null).

The store. The hermes-agent store behind held-out task 0cb3760383’s index (built by v4.22.1) has 474,232 synapse edges, all structural. It was scaled to the reported machine’s 1,272,023 edges: its structural edges copied under renamed node ids (1,192,985), plus 79,038 personal edges with random weights and ages up to 30 days, 7,904 transitions and 51,919 node activations; 1.07 GB. The learned rows are synthetic, so this measures how long the work takes on a store of that size, not what a real one’s export says. The recipe is in the raw results.

1,272,023 edges, M3 hook: mean hook: range hook under 8 s done: mean done: range
v4.23.0, idle (load average 2.5) 4.34 s 4.12–5.19 s 5 of 5 4.34 s 4.12–5.19 s
v4.23.1, idle (2.3) 0.20 s 0.18–0.22 s 5 of 5 4.39 s 4.16–5.18 s
v4.23.0, six busy loops (6.3) 7.00 s 6.70–8.03 s 4 of 5 7.00 s 6.70–8.03 s
v4.23.1, six busy loops (8.2) 0.33 s 0.25–0.62 s 5 of 5 7.48 s 6.87–8.21 s

Every sample returned the same 406-character recap. The work takes as long as it did; the hook no longer waits for it. Under a profiler (idle, v4.23.0) the hook’s 3.96 s was 3.49 s of export (the hub query 2.12 s, the strongest pairs 1.19 s) and 0.44 s of decay tick, and those passes are untouched here.

A Hermes first turn on that store. With the graph cache written, the prompt-submit call that follows took 1.36–1.43 s when it ran right after session-start, with the detached process running beside it, and 1.34–1.38 s on its own, returning the same block (3 calls each, idle). The first turn’s two calls come to about 1.6 s, against about 5.7 s with v4.23.0’s session-start.

On the Linux machine where 6.3–7.7 s was seen (32 cores, Hermes 0.22.5, the 1,272,023-edge store, the memory export on), through the installed plugin’s own pre_llm_call at its default 8 s, with a recap to return:

Linux, first turns (session-start + prompt-submit) Time Recap delivered
v4.23.0, eight busy loops 8.5–10.6 s (3 turns) 3 of 3, each call just under 8 s
v4.23.1, idle 2.0–2.1 s (4 turns) 4 of 4
v4.23.1, eight busy loops 2.4–3.6 s (4 turns) 4 of 4

The detached process finished 4.1 s (idle) and 5.8 s (busy) after the call began, and each time the decay tick had advanced meta.last_decay and the export had rewritten SYNAPSE_MEMORY.md. At a load of 10–12, before this change, a first turn took 12.0 s and its session-start call was stopped. One store, one machine; the numbers say how much of the call the store work was, not how long it takes elsewhere. Raw results: bench/hook_latency/session-start-hermes-agent-1.27M-m3.json.

Reproduce, from a source checkout, on a copy of a project with a synapse store (the hook writes to it, as a session start does; on APFS cp -cR clones a large index instantly): python -m tests.benchmark.session_start_latency <project-copy> --runs 5; for an older NeuralMind, put its checkout on PYTHONPATH.

What it doesn’t change

Tests

tests/test_hermes_plugin.py checks that:

The existing tests run as on older Hermes, where the plugin context has no session_cwd.

Upgrading

The session-start change is in the hook the plugin runs, so upgrading NeuralMind is enough for it. The session-directory change is in the plugin, which is a copy, so re-run the installer too:

pip install -U neuralmind
neuralmind install-hermes-plugin

A Hermes gateway that’s already running keeps the plugin code it loaded. Reload it:

hermes plugins disable neuralmind && hermes plugins enable neuralmind

That printed Gateway reloaded plugins on Hermes 0.22.5; restarting the gateway works too. If you set NEURALMIND_PROJECT or NEURALMIND_SYNAPSE_EXPORT=0 on the command you start Hermes with, you can drop them: on Hermes 0.22.2 and later they never reached the plugin, and from this release it doesn’t need them.

Use cases