Skip to content

[BOUNTY $100] Memanto + Developer Skills: Global Memory Wrapper (#508)#596

Open
mkcash wants to merge 2 commits into
moorcheh-ai:mainfrom
mkcash:skills-memanto-508
Open

[BOUNTY $100] Memanto + Developer Skills: Global Memory Wrapper (#508)#596
mkcash wants to merge 2 commits into
moorcheh-ai:mainfrom
mkcash:skills-memanto-508

Conversation

@mkcash

@mkcash mkcash commented May 29, 2026

Copy link
Copy Markdown

Memanto + Developer Skills Integration

Memanto as a global memory companion across the mattpocock/skills ecosystem.

Problem

Each CLI skill execution is isolated - context from one skill is invisible when running another.

Solution

Memanto acts as a persistent memory layer that:

  1. Captures skill inputs and outputs automatically
  2. Distills engineering decisions using pattern matching
  3. Injects relevant past context into new skill invocations
  4. Builds a growing knowledge graph of developer preferences

Files

  • examples/skills-memanto/memanto_skill_wrapper.py - CLI wrapper with Memanto integration
  • examples/skills-memanto/README.md - Documentation and usage guide

Summary by CodeRabbit

  • New Features

    • Added Memanto integration for persistent memory across skill execution, enabling capture of execution history and context injection for future runs.
    • Introduced command-line interface supporting skill execution with memory retrieval and local history management.
  • Documentation

    • Added documentation detailing the integration workflow and usage instructions.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces examples/skills-memanto/, a new example demonstrating how Memanto provides persistent memory across developer CLI skill runs. It includes documentation describing the use case and workflow, plus a Python wrapper that captures execution history, queries prior context, injects it into skill runs, and stores results locally and to the Memanto brain.

Changes

Skills-Memanto Integration Example

Layer / File(s) Summary
Documentation and module overview
examples/skills-memanto/README.md, examples/skills-memanto/memanto_skill_wrapper.py (lines 1–16)
README introduces the persistent memory use case, workflow, and CLI examples. Module docstring explains the purpose of building a knowledge graph from captured skill executions and context injection.
Memory management and state persistence
examples/skills-memanto/memanto_skill_wrapper.py (lines 18–188)
SDK detection and configuration via environment variables. SkillMemoryManager loads/saves local history, queries Memanto for relevant context (with local fallback), extracts and stores "key decisions" to the remote brain, and produces memory summaries.
Skill execution and CLI orchestration
examples/skills-memanto/memanto_skill_wrapper.py (lines 193–306)
run_skill executes external commands via subprocess, capturing stdout/stderr and exit codes with timeout handling. main() parses CLI arguments, resolves skill input, retrieves prior context, executes the skill, stores results with metadata, and exits using the skill's return code. Module entry point wires the script for execution.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • het0814

Poem

A rabbit weaves memories through CLI's flow,
Capturing skills and letting them grow.
Each hop builds context for paths yet untread,
A knowledge graph stitched from what came ahead. 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly references the main change—integrating Memanto as a memory wrapper for the Developer Skills ecosystem—which aligns with the PR's primary objective and the added files (memanto_skill_wrapper.py and README.md).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

🤖 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/skills-memanto/memanto_skill_wrapper.py`:
- Around line 99-106: The current construction of the memory dict (variable
"memory") stores raw "output", "query" and "workdir" which can capture sensitive
tokens, credentials or local paths; update the code to sanitize/redact before
persisting: add/use a sanitize function (e.g., sanitize_text or
redact_sensitive) to mask secrets via regex (API keys, tokens, filepaths), avoid
storing os.getcwd() directly (store None, basename only, or a hashed/opt-in
value), truncate and/or hash raw "output" and "query" instead of saving full
text, and add a configuration flag (e.g., allow_unredacted_memory=False) so
callers must opt-in to storing unredacted data; apply the same changes to the
other occurrence around lines 132-143 where "memory" is built.
- Around line 55-57: SkillMemoryManager._load_local_history() should guard
against malformed or unreadable HISTORY_FILE; wrap the
json.loads(HISTORY_FILE.read_text()) call in a try/except that catches
JSONDecodeError and OSError (or a broad Exception if you prefer) and return []
on failure so initialization doesn't crash, optionally logging the error if a
logger (e.g., logging.getLogger(__name__)) is available; keep the existing
behavior of returning [] when HISTORY_FILE does not exist.
- Around line 265-268: The current parsing of args.execute using
args.execute.split() breaks quoted arguments and will IndexError on empty input;
replace it with shell-style tokenization using shlex.split(args.execute) and
gracefully handle empty or malformed input: import shlex, call parts =
shlex.split(args.execute) inside the existing if args.execute: block (catching
ValueError from shlex.split for malformed quoting), then check if parts is
non-empty before assigning skill_name = parts[0] and skill_args = parts[1:],
otherwise log/raise a clear error or skip execution; refer to the args.execute,
parts, skill_name and skill_args variables to locate the code to change.

In `@examples/skills-memanto/README.md`:
- Around line 31-35: Update the fenced diagram block that begins with "Skill
Execution → Memanto captures context → Extracts key decisions → Stores in Brain"
to include a language identifier (e.g., add ```text) on the opening fence so the
block is ```text ... ```, which satisfies markdownlint MD040 and keeps the
README markdown lint-clean.
🪄 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: fa506180-05de-47d6-8ed4-4b7ee7c3ff8c

📥 Commits

Reviewing files that changed from the base of the PR and between dd38ad3 and 5afc3f8.

📒 Files selected for processing (2)
  • examples/skills-memanto/README.md
  • examples/skills-memanto/memanto_skill_wrapper.py

Comment on lines +55 to +57
if HISTORY_FILE.exists():
return json.loads(HISTORY_FILE.read_text())
return []

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 | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Print targeted lines around the reported range
sed -n '1,120p' examples/skills-memanto/memanto_skill_wrapper.py | nl -ba | sed -n '40,90p'

# Locate _load_local_history and HISTORY_FILE definition/usages
rg -n "_load_local_history|HISTORY_FILE|skill_history\.json" examples/skills-memanto/memanto_skill_wrapper.py

Repository: moorcheh-ai/memanto

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="examples/skills-memanto/memanto_skill_wrapper.py"

# Show lines around the reported range with line numbers (no nl dependency)
sed -n '40,90p' "$FILE" | cat -n

# Locate function and filename constant/usages
rg -n "_load_local_history|HISTORY_FILE|skill_history\.json" "$FILE"

Repository: moorcheh-ai/memanto

Length of output: 2817


Handle corrupted local history files gracefully.

SkillMemoryManager._load_local_history() directly json.loads(HISTORY_FILE.read_text()); a malformed/unreadable ~/.memanto/skill_history.json will raise (e.g., JSONDecodeError / OSError) and crash initialization instead of falling back to [].

Suggested fix
 def _load_local_history(self) -> list[dict]:
     """Load local fallback history."""
     if HISTORY_FILE.exists():
-        return json.loads(HISTORY_FILE.read_text())
+        try:
+            data = json.loads(HISTORY_FILE.read_text())
+            return data if isinstance(data, list) else []
+        except (json.JSONDecodeError, OSError):
+            return []
     return []
📝 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 HISTORY_FILE.exists():
return json.loads(HISTORY_FILE.read_text())
return []
if HISTORY_FILE.exists():
try:
data = json.loads(HISTORY_FILE.read_text())
return data if isinstance(data, list) else []
except (json.JSONDecodeError, OSError):
return []
return []
🤖 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/skills-memanto/memanto_skill_wrapper.py` around lines 55 - 57,
SkillMemoryManager._load_local_history() should guard against malformed or
unreadable HISTORY_FILE; wrap the json.loads(HISTORY_FILE.read_text()) call in a
try/except that catches JSONDecodeError and OSError (or a broad Exception if you
prefer) and return [] on failure so initialization doesn't crash, optionally
logging the error if a logger (e.g., logging.getLogger(__name__)) is available;
keep the existing behavior of returning [] when HISTORY_FILE does not exist.

Comment on lines +99 to +106
memory = {
"timestamp": datetime.now().isoformat(),
"skill": skill,
"query": query[:500],
"output": output[:1000],
"metadata": metadata or {},
"workdir": os.getcwd(),
}

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 | 🏗️ Heavy lift

Avoid storing raw command output and working directory without redaction controls.

This auto-captures potentially sensitive data (tokens, credentials, local usernames/paths) into local disk and remote memory by default.

Suggested direction
+import re
+
+def _redact_sensitive(self, text: str) -> str:
+    patterns = [
+        r'(?i)(api[_-]?key|token|password|secret)\s*[:=]\s*\S+',
+        r'-----BEGIN [A-Z ]+PRIVATE KEY-----[\s\S]+?-----END [A-Z ]+PRIVATE KEY-----',
+    ]
+    redacted = text
+    for p in patterns:
+        redacted = re.sub(p, r'\1=[REDACTED]', redacted)
+    return redacted
+
 # in store_skill_execution(...)
+safe_query = self._redact_sensitive(query)
+safe_output = self._redact_sensitive(output)
 memory = {
     "timestamp": datetime.now().isoformat(),
     "skill": skill,
-    "query": query[:500],
-    "output": output[:1000],
+    "query": safe_query[:500],
+    "output": safe_output[:1000],
     "metadata": metadata or {},
-    "workdir": os.getcwd(),
+    "workdir": os.getcwd() if os.environ.get("MEMANTO_INCLUDE_WORKDIR") == "1" else None,
 }

Also applies to: 132-143

🤖 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/skills-memanto/memanto_skill_wrapper.py` around lines 99 - 106, The
current construction of the memory dict (variable "memory") stores raw "output",
"query" and "workdir" which can capture sensitive tokens, credentials or local
paths; update the code to sanitize/redact before persisting: add/use a sanitize
function (e.g., sanitize_text or redact_sensitive) to mask secrets via regex
(API keys, tokens, filepaths), avoid storing os.getcwd() directly (store None,
basename only, or a hashed/opt-in value), truncate and/or hash raw "output" and
"query" instead of saving full text, and add a configuration flag (e.g.,
allow_unredacted_memory=False) so callers must opt-in to storing unredacted
data; apply the same changes to the other occurrence around lines 132-143 where
"memory" is built.

Comment on lines +265 to +268
if args.execute:
parts = args.execute.split()
skill_name = parts[0]
skill_args = parts[1:]

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 | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="examples/skills-memanto/memanto_skill_wrapper.py"
python - <<'PY'
import os
path="examples/skills-memanto/memanto_skill_wrapper.py"
print("exists:", os.path.exists(path))
print("size:", os.path.getsize(path) if os.path.exists(path) else None)
PY

# Print the relevant region with line numbers
nl -ba "$FILE" | sed -n '230,310p'

# Show argparse setup for args.execute (search for "execute" argument)
rg -n "add_argument\\(.*--execute|--execute|args\\.execute" "$FILE" -S

Repository: moorcheh-ai/memanto

Length of output: 150


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="examples/skills-memanto/memanto_skill_wrapper.py"

python - <<'PY'
path="examples/skills-memanto/memanto_skill_wrapper.py"
with open(path, "r", encoding="utf-8") as f:
    lines=f.readlines()
start=240
end=290
for i in range(start, min(end, len(lines))):
    print(f"{i+1}\t{lines[i].rstrip()}")
PY

rg -n "add_argument\\(.*--execute|--execute\\b|args\\.execute" "$FILE" -S

Repository: moorcheh-ai/memanto

Length of output: 1774


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="examples/skills-memanto/memanto_skill_wrapper.py"

# Show imports and argparse creation area
python - <<'PY'
path="examples/skills-memanto/memanto_skill_wrapper.py"
with open(path, "r", encoding="utf-8") as f:
    lines=f.readlines()
for i in range(1, min(80, len(lines))+1):
    print(f"{i}\t{lines[i-1].rstrip()}")
PY

# Show where --execute is defined
python - <<'PY'
path="examples/skills-memanto/memanto_skill_wrapper.py"
with open(path, "r", encoding="utf-8") as f:
    lines=f.readlines()
for i in range(180, min(260, len(lines))+1):
    if any(s in lines[i-1] for s in ["--execute", 'args = parser.parse_args', "parser ="]):
        pass
for i in range(200, min(250, len(lines))+1):
    print(f"{i}\t{lines[i-1].rstrip()}")
PY

Repository: moorcheh-ai/memanto

Length of output: 4814


Parse --execute with shell-style splitting and handle empty input

examples/skills-memanto/memanto_skill_wrapper.py currently uses args.execute.split(), which breaks quoted arguments and crashes on empty input (parts[0] raises IndexError).

Suggested fix
+import shlex
...
     if args.execute:
-        parts = args.execute.split()
+        parts = shlex.split(args.execute)
+        if not parts:
+            parser.error("--execute cannot be empty")
         skill_name = parts[0]
         skill_args = parts[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/skills-memanto/memanto_skill_wrapper.py` around lines 265 - 268, The
current parsing of args.execute using args.execute.split() breaks quoted
arguments and will IndexError on empty input; replace it with shell-style
tokenization using shlex.split(args.execute) and gracefully handle empty or
malformed input: import shlex, call parts = shlex.split(args.execute) inside the
existing if args.execute: block (catching ValueError from shlex.split for
malformed quoting), then check if parts is non-empty before assigning skill_name
= parts[0] and skill_args = parts[1:], otherwise log/raise a clear error or skip
execution; refer to the args.execute, parts, skill_name and skill_args variables
to locate the code to change.

Comment on lines +31 to +35
```
Skill Execution → Memanto captures context → Extracts key decisions → Stores in Brain
↑ ↓
└─────────────── Future skills retrieve past context ─────────────────────┘
```

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 | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced diagram block.

This currently triggers markdownlint MD040 and breaks lint-clean docs.

Suggested fix
-```
+```text
 Skill Execution → Memanto captures context → Extracts key decisions → Stores in Brain
      ↑                                                                         ↓
      └─────────────── Future skills retrieve past context ─────────────────────┘
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 31-31: 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/skills-memanto/README.md` around lines 31 - 35, Update the fenced
diagram block that begins with "Skill Execution → Memanto captures context →
Extracts key decisions → Stores in Brain" to include a language identifier
(e.g., add ```text) on the opening fence so the block is ```text ... ```, which
satisfies markdownlint MD040 and keeps the README markdown lint-clean.

@mkcash

mkcash commented May 29, 2026

Copy link
Copy Markdown
Author

Payment Information

Please send the bounty to one of the following addresses upon PR merge:

  • USDC (BNB Chain): 0xAC1d857cf2A69Ef2C0698F100a644bfE12A6123d
  • PayPal: ljwtitan@hotmail.com

Thank you!

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