dev branch with 0.6.17: fix codex plugin && new hermes plugin with 0.7.0 memory abstractions!#163
Conversation
Implements the Hermes v0.7.0 MemoryProvider ABC for Nowledge Mem, replacing the MCP-only connection with lifecycle hooks and native tools. Client (client.py): - Domain methods (search, save, update, delete, thread_search, etc.) that dispatch CLI vs HTTP internally - nmem CLI preferred (handles auth, remote URL, API key) - HTTP REST fallback for CLI-unavailable operations (labels listing, graph exploration) and when CLI is not installed - Repeatable -l flags for labels, correct --event-start flag - JSON parse error handling, HTTPError handling on GET Provider (provider.py): - Transport-agnostic: calls client domain methods, never touches CLI args or HTTP bodies - system_prompt_block: Working Memory + guidance injected automatically - prefetch: per-turn semantic recall - on_memory_write: mirrors user profile facts to Nowledge Mem - on_pre_compress: preserves external knowledge references - 9 native tools with nmem_ prefix - Comma-separated label parsing shared via _parse_csv helper Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CHANGELOG: fix stale MCP-over-HTTP reference, describe dual-transport - README: add transport section, document api_key in config - setup.sh: plugin mode (default) installs provider files and sets memory.provider in config.yaml; MCP mode unchanged - integrations.json: transport mcp->cli+http, distill true->false, threadSave method to none (planned for v0.6.0), add updateCommand - plugin.yaml: remove undeclared on_session_end hook Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Drop the entire urllib HTTP stack from client.py. The nmem CLI already handles server URL, API key, and remote access, so the HTTP fallback was duplicate config surface. - client.py: ~170 lines removed (urllib, _http_*, _headers, url/api_key) - provider.py: remove nmem_labels, nmem_neighbors, nmem_evolves tools (no CLI command exists yet; will add when CLI supports them) - update tool: drop add_labels param (CLI doesn't support label changes) - search/thread_search: require query (CLI needs positional arg) - config: only timeout remains; URL/API key managed by nmem CLI - integrations.json: transport cli+http → cli, graphExploration → false Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional id parameter to nmem_save tool schema and client.save() method. Agents can pass a stable key for create-or-update behavior instead of searching for internal memory IDs first. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dex plugin architecture The plugin was completely non-functional: wrong install path (~/.codex/plugins/ instead of ~/.codex/plugins/cache/local/.../local/), missing [features] plugins = true gate, and unsupported fields in plugin.json. Also replaced repo-level install docs with proper marketplace.json approach. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The guidance file referenced MCP-era tool names (memory_search, memory_add) and non-existent tools (memory_neighbors, memory_evolves_chain, thread_persist). Rewrote for plugin-mode nmem_* names and removed graph exploration section (MCP-only). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughReplaces MCP-based integrations with CLI-native plugin flows: updates integration metadata, Codex plugin manifest and docs, adds Hermes plugin code (client, provider, register), new setup/install scripts, README/AGENTS updates, and minor .gitignore change. Changes
Sequence DiagramsequenceDiagram
participant H as Hermes
participant P as NowledgeMemProvider
participant C as NowledgeMemClient
participant CLI as nmem CLI
H->>P: initialize(session_id)
P->>C: is_available()
C->>CLI: nmem --version
CLI-->>C: version output
C-->>P: availability
P->>C: health()
C->>CLI: nmem --json status
CLI-->>C: status JSON
C-->>P: health info
H->>P: system_prompt_block()
P->>C: working_memory()
C->>CLI: nmem --json wm read
CLI-->>C: WM JSON
P-->>H: formatted prompt block
H->>P: prefetch(query)
P->>C: search(query, limit)
C->>CLI: nmem --json m search ...
CLI-->>C: results JSON
P-->>H: recalled context
H->>P: handle_tool_call(nmem_search,...)
P->>C: search(...)
C->>CLI: nmem --json m search ...
CLI-->>C: JSON
C-->>P: results
P-->>H: JSON response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
nowledge-mem-hermes/AGENTS.md (1)
31-39: Consider adding language specifiers to fenced code blocks.Static analysis flagged several code blocks without language specifiers. Adding a language hint (e.g.,
```textor```bash) improves rendering and accessibility.📝 Example fix for one block
-``` +```text nmem_search query="your search query"</details> Also applies to: 50-52, 71-73, 77-79, 87-90 <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against the current code and only fix it if needed.
In
@nowledge-mem-hermes/AGENTS.mdaround lines 31 - 39, Several fenced code
blocks (e.g., the examples using nmem_search, nmem_thread_search, and
nmem_thread_messages) lack language specifiers which hurts rendering and
accessibility; update each fenced block to include an appropriate language hint
(for example usetext orbash before the snippet) for every occurrence
(including the other noted blocks at lines 50-52, 71-73, 77-79, 87-90) so that
examples like nmem_search query="your search query" and nmem_thread_messages
thread_id="" limit=8 render correctly.</details> </blockquote></details> <details> <summary>nowledge-mem-hermes/provider.py (2)</summary><blockquote> `333-334`: **Query length threshold of 10 characters may be restrictive.** Queries like "API keys" (8 chars) or "auth flow" (9 chars) would be skipped. Consider lowering to 5-6 characters or removing the check if the underlying search handles short queries gracefully. <details> <summary>📝 Suggested fix</summary> ```diff - if not query or len(query.strip()) < 10: + if not query or len(query.strip()) < 5: return "" ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@nowledge-mem-hermes/provider.py` around lines 333 - 334, The current query guard "if not query or len(query.strip()) < 10:" is too restrictive and drops valid short queries; update the check in provider.py (the conditional around query length) to either lower the threshold to 5 or remove the length-based guard entirely so shorter queries like "API keys" are processed; ensure any callers that expect an empty-string return still handle shorter queries and adjust or add tests for the function containing that conditional to cover short queries. ``` </details> --- `468-474`: **Silent exception swallowing in config loading.** Static analysis correctly identifies `try-except-pass` patterns that swallow exceptions without logging. While these are non-critical config paths, logging at debug level would aid troubleshooting. <details> <summary>📝 Suggested fix</summary> ```diff if config_path.exists(): try: existing = json.loads(config_path.read_text()) - except Exception: - pass + except Exception as e: + logger.debug("Failed to read existing config: %s", e) existing.update(values) ``` ```diff if config_path.exists(): try: cfg = json.loads(config_path.read_text()) return int(cfg.get("timeout", 30)) - except Exception: - pass + except Exception as e: + logger.debug("Failed to load timeout from config: %s", e) return 30 ``` </details> Also applies to: 498-504 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@nowledge-mem-hermes/provider.py` around lines 468 - 474, The try/except that reads JSON into existing currently swallows all exceptions; change the except in that block (and the similar block around lines 498-504) to catch Exception as e and log the error at debug level using the module logger before continuing (e.g., include config_path and the exception message), then proceed to update existing and write the file; reference the existing, config_path, values variables and the logger in your change so callers can diagnose malformed or unreadable config files. ``` </details> </blockquote></details> </blockquote></details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary>Verify each finding against the current code and only fix it if needed.
Inline comments:
In@nowledge-mem-codex-plugin/README.md:
- Around line 69-74: The README's install sequence copies into
./.agents/nowledge-mem before ensuring ./.agents exists; update the steps so the
.agents directory is created first (ensure the mkdir -p .agents/plugins command
runs before the cp into ./.agents/nowledge-mem) so the cp target directory
always exists and the repo-level install won’t fail on a clean checkout.In
@nowledge-mem-hermes/client.py:
- Around line 142-145: The delete_many method (delete_many) currently calls
self._cli with ["m", "delete"] + memory_ids + ["-f"] and will construct a forced
delete with no IDs if memory_ids is empty; add an explicit non-empty check at
the start of delete_many to guard against empty input (e.g., if not memory_ids:
raise ValueError("memory_ids must be a non-empty list") or return an appropriate
error), so the method never invokes self._cli when memory_ids is empty.In
@nowledge-mem-hermes/README.md:
- Around line 108-114: The README example timeout value (the "timeout" key in
the example JSON) conflicts with the default used in provider.py (default 30);
update the README example JSON to use "timeout": 30 so it matches provider.py's
default (or alternatively update provider.py's default if you intend 60) —
change the example's timeout value to 30 to keep docs and the provider.py
default consistent.In
@nowledge-mem-hermes/setup.sh:
- Around line 74-106: The script currently uses broad grep checks against
$CONFIG which can falsely report success ifprovider:andnowledge-memoccur
anywhere in the file; update the detection logic to ensure the provider is set
specifically under the memory: section (e.g., detect a "memory:" block and check
the indented "provider:" line directly beneath it using a targeted regex or a
small awk/grep block that looks for '^memory:' then an indented
'^\sprovider:\s"nowledge-mem"' before declaring success), and modify the
action-needed branch (the branch that prints "[action needed] $CONFIG has a
memory: section but provider is not set.") to exit non-zero (or otherwise
prevent the script from continuing to the final success messages/exit 0) so the
script does not report successful installation when configuration is incomplete;
reference the CONFIG variable checks and the final exit 0/installation messages
when making these changes.
Nitpick comments:
In@nowledge-mem-hermes/AGENTS.md:
- Around line 31-39: Several fenced code blocks (e.g., the examples using
nmem_search, nmem_thread_search, and nmem_thread_messages) lack language
specifiers which hurts rendering and accessibility; update each fenced block to
include an appropriate language hint (for example usetext orbash before
the snippet) for every occurrence (including the other noted blocks at lines
50-52, 71-73, 77-79, 87-90) so that examples like nmem_search query="your search
query" and nmem_thread_messages thread_id="" limit=8 render correctly.In
@nowledge-mem-hermes/provider.py:
- Around line 333-334: The current query guard "if not query or
len(query.strip()) < 10:" is too restrictive and drops valid short queries;
update the check in provider.py (the conditional around query length) to either
lower the threshold to 5 or remove the length-based guard entirely so shorter
queries like "API keys" are processed; ensure any callers that expect an
empty-string return still handle shorter queries and adjust or add tests for the
function containing that conditional to cover short queries.- Around line 468-474: The try/except that reads JSON into existing currently
swallows all exceptions; change the except in that block (and the similar block
around lines 498-504) to catch Exception as e and log the error at debug level
using the module logger before continuing (e.g., include config_path and the
exception message), then proceed to update existing and write the file;
reference the existing, config_path, values variables and the logger in your
change so callers can diagnose malformed or unreadable config files.</details> <details> <summary>🪄 Autofix (Beta)</summary> Fix all unresolved CodeRabbit comments on this PR: - [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended) - [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes </details> --- <details> <summary>ℹ️ Review info</summary> <details> <summary>⚙️ Run configuration</summary> **Configuration used**: defaults **Review profile**: CHILL **Plan**: Pro **Run ID**: `c19ff704-4f3b-47f6-9451-f2b0759f0a33` </details> <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between e5b897c0f0e05c68ae7a743ed2cd9c71ddc62a3f and 6df8f83a1c428c86793558ea60ebe09e218f97b3. </details> <details> <summary>📒 Files selected for processing (13)</summary> * `.gitignore` * `integrations.json` * `nowledge-mem-codex-plugin/.codex-plugin/plugin.json` * `nowledge-mem-codex-plugin/CHANGELOG.md` * `nowledge-mem-codex-plugin/README.md` * `nowledge-mem-hermes/AGENTS.md` * `nowledge-mem-hermes/CHANGELOG.md` * `nowledge-mem-hermes/README.md` * `nowledge-mem-hermes/__init__.py` * `nowledge-mem-hermes/client.py` * `nowledge-mem-hermes/plugin.yaml` * `nowledge-mem-hermes/provider.py` * `nowledge-mem-hermes/setup.sh` </details> <details> <summary>💤 Files with no reviewable changes (1)</summary> * nowledge-mem-codex-plugin/.codex-plugin/plugin.json </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
| if [ -f "$CONFIG" ] && grep -qF "provider:" "$CONFIG" && grep -qF "nowledge-mem" "$CONFIG"; then | ||
| echo "[ok] memory.provider already set in $CONFIG" | ||
| elif [ ! -f "$CONFIG" ]; then | ||
| cat > "$CONFIG" << 'YAML' | ||
| memory: | ||
| provider: "nowledge-mem" | ||
| YAML | ||
| echo "[ok] Created $CONFIG with memory.provider: nowledge-mem" | ||
| elif grep -qF "memory:" "$CONFIG"; then | ||
| # memory section exists but provider not set — inform user | ||
| echo "" | ||
| echo "[action needed] $CONFIG has a memory: section but provider is not set." | ||
| echo "Add the following under your memory: block:" | ||
| echo "" | ||
| echo ' provider: "nowledge-mem"' | ||
| echo "" | ||
| else | ||
| # No memory section — append it | ||
| printf '\nmemory:\n provider: "nowledge-mem"\n' >> "$CONFIG" | ||
| echo "[ok] Added memory.provider to $CONFIG" | ||
| fi | ||
|
|
||
| # Remove MCP server config if present (plugin replaces it) | ||
| if [ -f "$CONFIG" ] && grep -qF "nowledge-mem:" "$CONFIG" && grep -qF "url:" "$CONFIG" && grep -qF "/mcp" "$CONFIG"; then | ||
| echo "[note] You can remove the nowledge-mem entry from mcp_servers: in $CONFIG" | ||
| echo " The plugin connects directly; MCP server config is no longer needed." | ||
| fi | ||
|
|
||
| echo "" | ||
| echo "Plugin installed to $PLUGIN_DIR" | ||
| echo "Restart Hermes, then test:" | ||
| echo ' "Search my memories for recent decisions"' | ||
| exit 0 |
There was a problem hiding this comment.
Provider detection can report success when setup is incomplete.
Line 74 matches any provider: plus any nowledge-mem anywhere in the file, which can mis-detect configuration. Also, after the action-needed branch (Lines 85–89), the script still exits successfully at Line 106.
🛠️ Proposed fix
+ NEEDS_MANUAL_CONFIG=false
+
+ has_nowledge_mem_provider() {
+ awk '
+ /^[[:space:]]*memory:[[:space:]]*$/ {in_memory=1; next}
+ in_memory && /^[^[:space:]]/ {in_memory=0}
+ in_memory && /^[[:space:]]*provider:[[:space:]]*"nowledge-mem"[[:space:]]*$/ {found=1}
+ END {exit(found ? 0 : 1)}
+ ' "$1"
+ }
+
# Set memory.provider in config.yaml
- if [ -f "$CONFIG" ] && grep -qF "provider:" "$CONFIG" && grep -qF "nowledge-mem" "$CONFIG"; then
+ if [ -f "$CONFIG" ] && has_nowledge_mem_provider "$CONFIG"; then
echo "[ok] memory.provider already set in $CONFIG"
elif [ ! -f "$CONFIG" ]; then
@@
elif grep -qF "memory:" "$CONFIG"; then
@@
echo ' provider: "nowledge-mem"'
echo ""
+ NEEDS_MANUAL_CONFIG=true
else
@@
fi
@@
echo "Restart Hermes, then test:"
echo ' "Search my memories for recent decisions"'
+ if $NEEDS_MANUAL_CONFIG; then
+ echo "[error] Plugin files installed, but config is incomplete."
+ exit 1
+ fi
exit 0
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if [ -f "$CONFIG" ] && grep -qF "provider:" "$CONFIG" && grep -qF "nowledge-mem" "$CONFIG"; then | |
| echo "[ok] memory.provider already set in $CONFIG" | |
| elif [ ! -f "$CONFIG" ]; then | |
| cat > "$CONFIG" << 'YAML' | |
| memory: | |
| provider: "nowledge-mem" | |
| YAML | |
| echo "[ok] Created $CONFIG with memory.provider: nowledge-mem" | |
| elif grep -qF "memory:" "$CONFIG"; then | |
| # memory section exists but provider not set — inform user | |
| echo "" | |
| echo "[action needed] $CONFIG has a memory: section but provider is not set." | |
| echo "Add the following under your memory: block:" | |
| echo "" | |
| echo ' provider: "nowledge-mem"' | |
| echo "" | |
| else | |
| # No memory section — append it | |
| printf '\nmemory:\n provider: "nowledge-mem"\n' >> "$CONFIG" | |
| echo "[ok] Added memory.provider to $CONFIG" | |
| fi | |
| # Remove MCP server config if present (plugin replaces it) | |
| if [ -f "$CONFIG" ] && grep -qF "nowledge-mem:" "$CONFIG" && grep -qF "url:" "$CONFIG" && grep -qF "/mcp" "$CONFIG"; then | |
| echo "[note] You can remove the nowledge-mem entry from mcp_servers: in $CONFIG" | |
| echo " The plugin connects directly; MCP server config is no longer needed." | |
| fi | |
| echo "" | |
| echo "Plugin installed to $PLUGIN_DIR" | |
| echo "Restart Hermes, then test:" | |
| echo ' "Search my memories for recent decisions"' | |
| exit 0 | |
| NEEDS_MANUAL_CONFIG=false | |
| has_nowledge_mem_provider() { | |
| awk ' | |
| /^[[:space:]]*memory:[[:space:]]*$/ {in_memory=1; next} | |
| in_memory && /^[^[:space:]]/ {in_memory=0} | |
| in_memory && /^[[:space:]]*provider:[[:space:]]*"nowledge-mem"[[:space:]]*$/ {found=1} | |
| END {exit(found ? 0 : 1)} | |
| ' "$1" | |
| } | |
| # Set memory.provider in config.yaml | |
| if [ -f "$CONFIG" ] && has_nowledge_mem_provider "$CONFIG"; then | |
| echo "[ok] memory.provider already set in $CONFIG" | |
| elif [ ! -f "$CONFIG" ]; then | |
| cat > "$CONFIG" << 'YAML' | |
| memory: | |
| provider: "nowledge-mem" | |
| YAML | |
| echo "[ok] Created $CONFIG with memory.provider: nowledge-mem" | |
| elif grep -qF "memory:" "$CONFIG"; then | |
| # memory section exists but provider not set — inform user | |
| echo "" | |
| echo "[action needed] $CONFIG has a memory: section but provider is not set." | |
| echo "Add the following under your memory: block:" | |
| echo "" | |
| echo ' provider: "nowledge-mem"' | |
| echo "" | |
| NEEDS_MANUAL_CONFIG=true | |
| else | |
| # No memory section — append it | |
| printf '\nmemory:\n provider: "nowledge-mem"\n' >> "$CONFIG" | |
| echo "[ok] Added memory.provider to $CONFIG" | |
| fi | |
| # Remove MCP server config if present (plugin replaces it) | |
| if [ -f "$CONFIG" ] && grep -qF "nowledge-mem:" "$CONFIG" && grep -qF "url:" "$CONFIG" && grep -qF "/mcp" "$CONFIG"; then | |
| echo "[note] You can remove the nowledge-mem entry from mcp_servers: in $CONFIG" | |
| echo " The plugin connects directly; MCP server config is no longer needed." | |
| fi | |
| echo "" | |
| echo "Plugin installed to $PLUGIN_DIR" | |
| echo "Restart Hermes, then test:" | |
| echo ' "Search my memories for recent decisions"' | |
| if $NEEDS_MANUAL_CONFIG; then | |
| echo "[error] Plugin files installed, but config is incomplete." | |
| exit 1 | |
| fi | |
| exit 0 |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nowledge-mem-hermes/setup.sh` around lines 74 - 106, The script currently
uses broad grep checks against $CONFIG which can falsely report success if
`provider:` and `nowledge-mem` occur anywhere in the file; update the detection
logic to ensure the provider is set specifically under the memory: section
(e.g., detect a "memory:" block and check the indented "provider:" line directly
beneath it using a targeted regex or a small awk/grep block that looks for
'^memory:' then an indented '^\\s*provider:\\s*\"nowledge-mem\"' before
declaring success), and modify the action-needed branch (the branch that prints
"[action needed] $CONFIG has a memory: section but provider is not set.") to
exit non-zero (or otherwise prevent the script from continuing to the final
success messages/exit 0) so the script does not report successful installation
when configuration is incomplete; reference the CONFIG variable checks and the
final exit 0/installation messages when making these changes.
…te detection Codex's serde silently ignores unknown fields, so this is safe. The desktop app reads version from plugin JSON to compare against the registry and show update badges. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bd379b7. Configure here.
|
|
||
| # Set memory.provider in config.yaml | ||
| if [ -f "$CONFIG" ] && grep -qF "provider:" "$CONFIG" && grep -qF "nowledge-mem" "$CONFIG"; then | ||
| echo "[ok] memory.provider already set in $CONFIG" |
There was a problem hiding this comment.
Config detection uses independent greps causing false positive
Medium Severity
The plugin-mode config detection checks for "provider:" and "nowledge-mem" as two independent grep calls. When upgrading from MCP mode, the config already has nowledge-mem: in the mcp_servers section. If any other section (e.g., LLM config) also contains a provider: key, both greps match independently, and the script incorrectly reports "memory.provider already set" — skipping the necessary config update. The plugin then silently fails to activate. Grepping for the combined string provider:.*nowledge-mem or 'provider: "nowledge-mem"' would avoid this false positive.
Reviewed by Cursor Bugbot for commit bd379b7. Configure here.
- Codex README: mkdir .agents before cp in repo-level install - Hermes client.py: guard delete_many against empty list, use unpacking - Hermes README: align timeout example (60 -> 30) with provider default - Hermes setup.sh: combine grep into single pattern to prevent false positive when provider: and nowledge-mem appear in separate sections; exit 1 when config needs manual intervention Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
nowledge-mem-hermes/README.md (1)
53-56: Consider addinguvxas the first CLI option.Recommend documenting
uvx --from nmem-cli nmemalongsidepip install nmem-clifor no-install and remote/macOS-friendly setups.Based on learnings: Install Nowledge Mem CLI using either
uvx --from nmem-cli nmem(recommended, no installation) orpip install nmem-cli, withuvxpreferred for macOS and remote servers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nowledge-mem-hermes/README.md` around lines 53 - 56, Update the CLI installation instructions to recommend uvx first and show the alternative pip install: add a sentence before the existing `pip install nmem-cli` line that documents using uvx (e.g., "Preferred: use uvx --from nmem-cli nmem for a no-install, macOS/remote-friendly setup"), and keep the existing `pip install nmem-cli` option as the fallback; reference the CLI names `uvx`, `nmem-cli`, and `nmem` in the text so readers know the exact commands to run.nowledge-mem-hermes/client.py (1)
38-47: Narrow exception handling in availability checks.Catching
Exceptionhere masks unexpected bugs. Prefer explicit subprocess-related exceptions so genuine logic errors still surface during debugging.♻️ Proposed fix
`@staticmethod` def is_available() -> bool: """Return True if ``nmem`` CLI is on PATH and responds.""" try: r = subprocess.run( ["nmem", "--version"], capture_output=True, text=True, timeout=5, ) return r.returncode == 0 - except Exception: + except (FileNotFoundError, OSError, subprocess.SubprocessError, subprocess.TimeoutExpired): return False @@ def health(self) -> bool: """Check that Nowledge Mem is reachable.""" try: r = subprocess.run( ["nmem", "--json", "status"], capture_output=True, text=True, timeout=5, ) return r.returncode == 0 - except Exception: + except (FileNotFoundError, OSError, subprocess.SubprocessError, subprocess.TimeoutExpired): return FalseAlso applies to: 53-62
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nowledge-mem-hermes/client.py` around lines 38 - 47, The availability check currently catches Exception around the subprocess.run call which masks real bugs; replace the broad except Exception with specific subprocess-related exceptions (e.g., catch FileNotFoundError, subprocess.TimeoutExpired and subprocess.SubprocessError) for the subprocess.run(...) blocks so missing binary, timeouts, and subprocess failures return False while allowing other unexpected exceptions to propagate; apply the same change to the other identical subprocess.run(...) check in this file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@nowledge-mem-hermes/README.md`:
- Around line 13-15: Replace the installer invocation that fetches setup.sh from
the mutable main branch with a pinned release (use a specific git tag or commit
SHA in the URL that references setup.sh) and add verification steps: download a
corresponding checksum or signature (and verify it) before executing; update the
README examples (the bash <(curl -sL ... setup.sh) lines that reference
setup.sh) to use the pinned URL and include a short instruction to validate the
checksum/signature (or curl the checksum file and verify) so users do not
execute code from a moving branch.
---
Nitpick comments:
In `@nowledge-mem-hermes/client.py`:
- Around line 38-47: The availability check currently catches Exception around
the subprocess.run call which masks real bugs; replace the broad except
Exception with specific subprocess-related exceptions (e.g., catch
FileNotFoundError, subprocess.TimeoutExpired and subprocess.SubprocessError) for
the subprocess.run(...) blocks so missing binary, timeouts, and subprocess
failures return False while allowing other unexpected exceptions to propagate;
apply the same change to the other identical subprocess.run(...) check in this
file.
In `@nowledge-mem-hermes/README.md`:
- Around line 53-56: Update the CLI installation instructions to recommend uvx
first and show the alternative pip install: add a sentence before the existing
`pip install nmem-cli` line that documents using uvx (e.g., "Preferred: use uvx
--from nmem-cli nmem for a no-install, macOS/remote-friendly setup"), and keep
the existing `pip install nmem-cli` option as the fallback; reference the CLI
names `uvx`, `nmem-cli`, and `nmem` in the text so readers know the exact
commands to run.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 85f693a5-4d92-4924-9a78-aaecdc6bb005
📒 Files selected for processing (4)
nowledge-mem-codex-plugin/README.mdnowledge-mem-hermes/README.mdnowledge-mem-hermes/client.pynowledge-mem-hermes/setup.sh
🚧 Files skipped from review as they are similar to previous changes (2)
- nowledge-mem-hermes/setup.sh
- nowledge-mem-codex-plugin/README.md
| ```bash | ||
| bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) | ||
| ``` |
There was a problem hiding this comment.
Pin installer sources instead of executing from mutable main.
These commands execute remote code directly from a moving branch. Please pin to a release tag/commit (and ideally verify checksums) to reduce supply-chain risk for users.
🔒 Suggested docs hardening
-bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh)
+# Example: pin to a released tag
+bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/v0.6.17/nowledge-mem-hermes/setup.sh)
@@
- curl -sLO "https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/$f"
+ curl -sLO "https://raw.githubusercontent.com/nowledge-co/community/v0.6.17/nowledge-mem-hermes/$f"
@@
-bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh) --mcp
+bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/v0.6.17/nowledge-mem-hermes/setup.sh) --mcpAlso applies to: 30-32, 45-47
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nowledge-mem-hermes/README.md` around lines 13 - 15, Replace the installer
invocation that fetches setup.sh from the mutable main branch with a pinned
release (use a specific git tag or commit SHA in the URL that references
setup.sh) and add verification steps: download a corresponding checksum or
signature (and verify it) before executing; update the README examples (the bash
<(curl -sL ... setup.sh) lines that reference setup.sh) to use the pinned URL
and include a short instruction to validate the checksum/signature (or curl the
checksum file and verify) so users do not execute code from a moving branch.


Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Note
Medium Risk
Adds a new Hermes memory-provider plugin with per-turn recall and write mirroring via the
nmemCLI, plus an updated installer script; behavior changes could affect Hermes session prompting and memory writes. Codex changes are mostly install/docs fixes, but incorrect paths/config could still break plugin discovery.Overview
Introduces a native Hermes memory provider plugin (v0.5.0) that integrates via Hermes v0.7.0+ lifecycle hooks: automatic Working Memory injection, per-turn prefetch recall, tool schema/dispatch for
nmem_*commands, and mirroring Hermes user-profile writes into Nowledge Mem via a background save.Updates Hermes installation to support two modes in
setup.sh(default--pluginvs--mcp), and rewrites docs/guidance to reflect plugin mode vs MCP-only mode and the newnmem_tool naming.Fixes the Codex CLI plugin packaging/install flow (v0.1.1): corrects the Codex plugin store path and required
~/.codex/config.tomlfeature gate, adjusts repo-level install to usemarketplace.json, and simplifies.codex-plugin/plugin.jsonto only fields Codex parses. Also updatesintegrations.jsonentries and.gitignoreto exclude__pycache__.Reviewed by Cursor Bugbot for commit bd379b7. Bugbot is set up for automated code reviews on this repo. Configure here.