Skip to content

dev branch with 0.6.17: fix codex plugin && new hermes plugin with 0.7.0 memory abstractions!#163

Merged
wey-gu merged 9 commits into
mainfrom
dev_0617
Apr 5, 2026
Merged

dev branch with 0.6.17: fix codex plugin && new hermes plugin with 0.7.0 memory abstractions!#163
wey-gu merged 9 commits into
mainfrom
dev_0617

Conversation

@wey-gu

@wey-gu wey-gu commented Apr 5, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Hermes native memory-provider plugin with automatic working-memory injection, deterministic lifecycle hooks, CLI-backed transport, native nmem tools, and a stdlib CLI client.
  • Bug Fixes

    • Fixed plugin install/update paths and added required feature gate; cleaned manifest metadata and adjusted integration metadata for CLI/plugin transport.
  • Documentation

    • Updated install/setup/troubleshooting for plugin vs MCP modes, tool naming, and changelogs.

Note

Medium Risk
Adds a new Hermes memory-provider plugin with per-turn recall and write mirroring via the nmem CLI, 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 --plugin vs --mcp), and rewrites docs/guidance to reflect plugin mode vs MCP-only mode and the new nmem_ tool naming.

Fixes the Codex CLI plugin packaging/install flow (v0.1.1): corrects the Codex plugin store path and required ~/.codex/config.toml feature gate, adjusts repo-level install to use marketplace.json, and simplifies .codex-plugin/plugin.json to only fields Codex parses. Also updates integrations.json entries and .gitignore to exclude __pycache__.

Reviewed by Cursor Bugbot for commit bd379b7. Bugbot is set up for automated code reviews on this repo. Configure here.

wey-gu and others added 7 commits April 4, 2026 18:29
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>
@coderabbitai

coderabbitai Bot commented Apr 5, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Replaces 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

Cohort / File(s) Summary
VCS ignore
\.gitignore
Add __pycache__ to ignore Python bytecode caches.
Integration registry
integrations.json
Bump codex-cli to 0.1.1 and change Codex install path to ~/.codex/plugins/cache/local/...; convert hermes from connector/MCP (0.4.0) to plugin/CLI (0.5.0), change transport to cli, adjust capability flags and threadSave method, update install commands and toolNaming to explicit nmem_* tools.
Codex plugin manifest
nowledge-mem-codex-plugin/.codex-plugin/plugin.json
Bump plugin version to 0.1.1 and remove non-interface metadata fields (author, homepage, repository, license, keywords).
Codex docs & changelog
nowledge-mem-codex-plugin/README.md, nowledge-mem-codex-plugin/CHANGELOG.md
Change install/update paths to cache-local layout, require [features] plugins = true, add repo-level marketplace.json instructions, update troubleshooting and changelog entry for v0.1.1.
Hermes docs & changelog
nowledge-mem-hermes/README.md, nowledge-mem-hermes/AGENTS.md, nowledge-mem-hermes/CHANGELOG.md
Rewrite docs for plugin-mode: replace MCP tool names with nmem_*, document provider lifecycle hooks and upsert-by-id semantics, separate MCP-only graph/tools, add 0.5.0 release notes.
Hermes plugin code
nowledge-mem-hermes/__init__.py, nowledge-mem-hermes/client.py, nowledge-mem-hermes/provider.py
Add register(ctx) entrypoint; implement NowledgeMemClient (CLI wrapper calling nmem --json) and NowledgeMemProvider implementing Hermes memory-provider lifecycle hooks, tool dispatch, config persistence, background mirroring, and degraded/no-op behavior when CLI unavailable.
Hermes install & manifest
nowledge-mem-hermes/plugin.yaml, nowledge-mem-hermes/setup.sh
Add plugin.yaml (v0.5.0) and update setup.sh with --plugin (default) vs --mcp modes, local-vs-remote file sourcing, install into ~/.hermes/plugins/memory/nowledge-mem/, and automatic memory.provider config insertion.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped from MCP to nmem CLI,
plugins nested where caches lie,
Hermes listens, Codex too,
shelling out the facts anew,
Nowledge Mem hums — a helpful sigh.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the primary changes: fixes to the Codex plugin (v0.1.1) and introduction of a new Hermes plugin (v0.5.0) with memory provider capabilities for Hermes v0.7.0.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev_0617

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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., ```text or ```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.md around 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 use text or bash 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 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
    '^\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 use text or bash 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 -->

Comment thread nowledge-mem-codex-plugin/README.md
Comment thread nowledge-mem-hermes/client.py
Comment thread nowledge-mem-hermes/README.md
Comment thread nowledge-mem-hermes/setup.sh Outdated
Comment on lines +74 to +106
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Suggested change
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>
@wey-gu

wey-gu commented Apr 5, 2026

Copy link
Copy Markdown
Member Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

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>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
nowledge-mem-hermes/README.md (1)

53-56: Consider adding uvx as the first CLI option.

Recommend documenting uvx --from nmem-cli nmem alongside pip install nmem-cli for no-install and remote/macOS-friendly setups.

Based on learnings: Install Nowledge Mem CLI using either uvx --from nmem-cli nmem (recommended, no installation) or pip install nmem-cli, with uvx preferred 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 Exception here 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 False

Also 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

📥 Commits

Reviewing files that changed from the base of the PR and between bd379b7 and 95bda36.

📒 Files selected for processing (4)
  • nowledge-mem-codex-plugin/README.md
  • nowledge-mem-hermes/README.md
  • nowledge-mem-hermes/client.py
  • nowledge-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

Comment on lines 13 to 15
```bash
bash <(curl -sL https://raw.githubusercontent.com/nowledge-co/community/main/nowledge-mem-hermes/setup.sh)
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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) --mcp

Also 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant