feat: add Memanto global memory integration for claude-code skills (#508)#607
feat: add Memanto global memory integration for claude-code skills (#508)#607zhangzeyu-ai wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughAdds a new Memanto memory layer example under ChangesMemanto Memory Layer Example
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/claudecode-skills-memanto/README.md`:
- Line 20: The README's bash example uses Windows CMD syntax "set
MOORCHEH_API_KEY=sk-xxxxxxx"; update that line (the string "set
MOORCHEH_API_KEY=sk-xxxxxxx") to use POSIX shell syntax "export
MOORCHEH_API_KEY=..." for the bash block, or alternatively document both
variants (show "export MOORCHEH_API_KEY=..." for bash/zsh and "set
MOORCHEH_API_KEY=..." for Windows CMD/PowerShell) so the setup instructions
match the annotated shell.
In `@examples/claudecode-skills-memanto/scripts/memanto_memory.py`:
- Line 43: Update the user-facing initialization guidance in memanto_memory.py:
replace the existing print("Error: not initialized. Run 'memanto init' first.")
message with one that instructs the correct CLI for this example, e.g. mention
running "python scripts/memanto_memory.py init" (or the appropriate invocation
used by this script) so users know to run that exact command to initialize;
locate and update the print statement in memanto_memory.py.
- Line 219: The --confidence arg currently allows any float; add validation at
parse time by replacing p.add_argument("--confidence", type=float, ...) with a
validator function (e.g., def confidence_type(v): try: f=float(v) except: raise
argparse.ArgumentTypeError(...) ; if not 0.0 <= f <= 1.0: raise
argparse.ArgumentTypeError("confidence must be between 0 and 1") ; return f) and
pass type=confidence_type to p.add_argument so parsing fails fast with a clear
error for out-of-range values; reference the p.add_argument("--confidence", ...)
call when making the change.
- Line 136: In cmd_recall, guard the score formatting by safely converting score
to float before building score_str: instead of directly calling float(score) in
score_str, try converting score in a try/except (catch TypeError/ValueError) or
check isinstance(score, (int, float)); on failure or non-numeric values treat it
as None or use a placeholder (e.g., "N/A") and then build score_str accordingly
so non-numeric backend values won't raise exceptions.
In `@examples/claudecode-skills-memanto/SKILL.md`:
- Around line 52-63: The fenced code block containing the example transcript
(the block starting with "# Session 1 — store decisions" and the three shell
lines) is missing a language tag and triggers MD040; update the opening fence
from ``` to ```text (or another appropriate language) so the block is recognized
as plain text and the markdown linter stops flagging it.
🪄 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 Plus
Run ID: f1ca04f5-078c-44d9-9ed7-45822c25857b
📒 Files selected for processing (4)
examples/claudecode-skills-memanto/README.mdexamples/claudecode-skills-memanto/SKILL.mdexamples/claudecode-skills-memanto/requirements.txtexamples/claudecode-skills-memanto/scripts/memanto_memory.py
| # 2. Get a free API key at https://moorcheh.ai | ||
|
|
||
| # 3. Set the key | ||
| set MOORCHEH_API_KEY=sk-xxxxxxx |
There was a problem hiding this comment.
Fix shell command mismatch in setup instructions.
This block is marked bash, but set MOORCHEH_API_KEY=... is Windows CMD syntax and will fail in bash/zsh. Use export MOORCHEH_API_KEY=... (or document both shells explicitly).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/claudecode-skills-memanto/README.md` at line 20, The README's bash
example uses Windows CMD syntax "set MOORCHEH_API_KEY=sk-xxxxxxx"; update that
line (the string "set MOORCHEH_API_KEY=sk-xxxxxxx") to use POSIX shell syntax
"export MOORCHEH_API_KEY=..." for the bash block, or alternatively document both
variants (show "export MOORCHEH_API_KEY=..." for bash/zsh and "set
MOORCHEH_API_KEY=..." for Windows CMD/PowerShell) so the setup instructions
match the annotated shell.
|
|
||
| def _load_config(): | ||
| if not CONFIG_FILE.exists(): | ||
| print("Error: not initialized. Run 'memanto init' first.") |
There was a problem hiding this comment.
Correct the init guidance string to match this CLI.
The message says Run 'memanto init' first. but this example uses python scripts/memanto_memory.py init. This mismatch makes recovery harder when config is missing.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/claudecode-skills-memanto/scripts/memanto_memory.py` at line 43,
Update the user-facing initialization guidance in memanto_memory.py: replace the
existing print("Error: not initialized. Run 'memanto init' first.") message with
one that instructs the correct CLI for this example, e.g. mention running
"python scripts/memanto_memory.py init" (or the appropriate invocation used by
this script) so users know to run that exact command to initialize; locate and
update the print statement in memanto_memory.py.
| content = m.get("content", m.get("metadata", {}).get("content", "")) | ||
| mtype = m.get("type", m.get("metadata", {}).get("memory_type", "?")) | ||
| score = m.get("score", m.get("similarity", None)) | ||
| score_str = f" [score: {float(score):.3f}]" if score is not None else "" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== File: examples/claudecode-skills-memanto/scripts/memanto_memory.py (lines 110-170) ==="
nl -ba examples/claudecode-skills-memanto/scripts/memanto_memory.py | sed -n '110,170p'
echo
echo "=== Search: float(score) occurrences ==="
rg -n "float\(score\)" examples/claudecode-skills-memanto/scripts/memanto_memory.py || true
rg -n "score_str|score_val|m\.get\(\"score\"" examples/claudecode-skills-memanto/scripts/memanto_memory.py || true
echo
echo "=== Repo-wide search for float(score) in this example ==="
rg -n "float\(score\)" examples/claudecode-skills-memanto || trueRepository: moorcheh-ai/memanto
Length of output: 215
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== File: examples/claudecode-skills-memanto/scripts/memanto_memory.py (lines 110-170) ==="
cat -n examples/claudecode-skills-memanto/scripts/memanto_memory.py | sed -n '110,170p'
echo
echo "=== Search: float(score) occurrences (target file) ==="
rg -n "float\(score\)" examples/claudecode-skills-memanto/scripts/memanto_memory.py || true
echo
echo "=== Search: score formatting vars (target file) ==="
rg -n "score_str|score_val|m\.get\(\"score\"" examples/claudecode-skills-memanto/scripts/memanto_memory.py || true
echo
echo "=== Repo-wide search for float(score) in this example ==="
rg -n "float\(score\)" examples/claudecode-skills-memanto || trueRepository: moorcheh-ai/memanto
Length of output: 3264
Guard score formatting in cmd_recall (line 136) against non-numeric backend values.
float(score) will raise TypeError/ValueError if the backend returns a non-numeric value (even when score is not None). Add a safe conversion fallback before formatting.
Proposed fix
- score = m.get("score", m.get("similarity", None))
- score_str = f" [score: {float(score):.3f}]" if score is not None else ""
+ score = m.get("score", m.get("similarity", None))
+ try:
+ score_val = float(score) if score is not None else None
+ except (TypeError, ValueError):
+ score_val = None
+ score_str = f" [score: {score_val:.3f}]" if score_val is not None else ""🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/claudecode-skills-memanto/scripts/memanto_memory.py` at line 136, In
cmd_recall, guard the score formatting by safely converting score to float
before building score_str: instead of directly calling float(score) in
score_str, try converting score in a try/except (catch TypeError/ValueError) or
check isinstance(score, (int, float)); on failure or non-numeric values treat it
as None or use a placeholder (e.g., "N/A") and then build score_str accordingly
so non-numeric backend values won't raise exceptions.
| p.add_argument("content", help="Memory content") | ||
| p.add_argument("--type", "-t", help="Memory type (auto-detected if omitted)") | ||
| p.add_argument("--tags", nargs="*", default=[], help="Tags") | ||
| p.add_argument("--confidence", type=float, default=0.8, help="Confidence 0–1") |
There was a problem hiding this comment.
Validate --confidence range at parse time.
Help text says 0–1, but values outside that range are currently accepted and passed through. Add argparse validation to fail fast with a clear error.
Proposed fix
+ def _confidence_01(value):
+ v = float(value)
+ if not 0.0 <= v <= 1.0:
+ raise argparse.ArgumentTypeError("confidence must be between 0 and 1")
+ return v
...
- p.add_argument("--confidence", type=float, default=0.8, help="Confidence 0–1")
+ p.add_argument("--confidence", type=_confidence_01, default=0.8, help="Confidence 0–1")📝 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.
| p.add_argument("--confidence", type=float, default=0.8, help="Confidence 0–1") | |
| def _confidence_01(value): | |
| v = float(value) | |
| if not 0.0 <= v <= 1.0: | |
| raise argparse.ArgumentTypeError("confidence must be between 0 and 1") | |
| return v | |
| p.add_argument("--confidence", type=_confidence_01, default=0.8, help="Confidence 0–1") |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/claudecode-skills-memanto/scripts/memanto_memory.py` at line 219,
The --confidence arg currently allows any float; add validation at parse time by
replacing p.add_argument("--confidence", type=float, ...) with a validator
function (e.g., def confidence_type(v): try: f=float(v) except: raise
argparse.ArgumentTypeError(...) ; if not 0.0 <= f <= 1.0: raise
argparse.ArgumentTypeError("confidence must be between 0 and 1") ; return f) and
pass type=confidence_type to p.add_argument so parsing fails fast with a clear
error for out-of-range values; reference the p.add_argument("--confidence", ...)
call when making the change.
| ``` | ||
| # Session 1 — store decisions | ||
| → python scripts/memanto_memory.py remember "Chose FastAPI" "Picked FastAPI over Flask for async support and built-in validation" | ||
|
|
||
| # Session 2 — recall before starting | ||
| → python scripts/memanto_memory.py recall "API framework decision" | ||
| → [decision] Chose FastAPI — Picked FastAPI over Flask for async… | ||
|
|
||
| # Session 3 — ask a question | ||
| → python scripts/memanto_memory.py answer "why did we pick FastAPI?" | ||
| → Chose FastAPI for async support and built-in validation | ||
| ``` |
There was a problem hiding this comment.
Add a language to the fenced code block.
The example workflow fence is missing a language tag, which trips markdown linting (MD040). Use something like ```text for this transcript-style example.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 52-52: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/claudecode-skills-memanto/SKILL.md` around lines 52 - 63, The fenced
code block containing the example transcript (the block starting with "# Session
1 — store decisions" and the three shell lines) is missing a language tag and
triggers MD040; update the opening fence from ``` to ```text (or another
appropriate language) so the block is recognized as plain text and the markdown
linter stops flagging it.
|
We were blown away by the community's creativity and the sheer volume of high-quality submissions! After reviewing all the pull requests against the bounty's success matrix, we have decided to move forward with merging PR #692, which implemented a highly portable prompt-injection architecture via CLAUDE.md. We are closing this PR because it falls into one of the architectural approaches that we ultimately decided against for the ecosystem:
We deeply appreciate the time and engineering effort you put into this submission. The codebase was fantastic to review, and we hope to see you in future Moorcheh bounties! |
Summary
Adds a global memory layer for the mattpocock/skills ecosystem using Memanto.
Files
How it works
Claude reads SKILL.md ? calls python scripts/memanto_memory.py ? uses memanto's DirectClient ? stores/retrieves memories via the Moorcheh API. Cross-session persistence without needing a local server.
Social Media Showcase