Skip to content

feat: add Claude Code skills Memanto memory bridge#613

Open
attaboy11 wants to merge 8 commits into
moorcheh-ai:mainfrom
attaboy11:attaboy11/claudecode-skills-memanto-bridge
Open

feat: add Claude Code skills Memanto memory bridge#613
attaboy11 wants to merge 8 commits into
moorcheh-ai:mainfrom
attaboy11:attaboy11/claudecode-skills-memanto-bridge

Conversation

@attaboy11

@attaboy11 attaboy11 commented May 31, 2026

Copy link
Copy Markdown

Closes #508.

Summary

  • Adds examples/claudecode-skills-memanto, a lightweight before/after lifecycle bridge for developer skills.
  • before_skill(...) recalls relevant engineering memory and returns a compact context block for the next skill prompt.
  • after_skill(...) extracts durable decisions, preferences, quirks, constraints, and learnings from a completed skill transcript and stores them through Memanto.
  • Includes a real Memanto CLI backend plus an offline JSON backend so reviewers can run the example without a Moorcheh API key.
  • Adds a 30-second GIF at examples/claudecode-skills-memanto/assets/demo.gif.
  • Follow-up hardening adds API docs, safer offline JSON persistence, malformed-shape recovery, and reviewer smoke coverage.

Social showcase

Organic showcase link: https://x.com/ciprianimacovei/status/2061044237206950149?s=46&t=lY3sRT0pRNlqtaJrHuIX4w

Latest review state

  • Latest commit: 752f3bf
  • CodeRabbit: no actionable comments in the latest review
  • CodeRabbit pre-merge checks: 5/5 passed
  • Docstring coverage: 82.76%, above the required 80.00%

Verification

python3 -m compileall examples/claudecode-skills-memanto
python3 examples/claudecode-skills-memanto/run_cross_skill_demo.py --backend file --reset
python3 -m ruff check examples/claudecode-skills-memanto/memory_backends.py examples/claudecode-skills-memanto/skill_memory_bridge.py examples/claudecode-skills-memanto/run_cross_skill_demo.py examples/claudecode-skills-memanto/make_demo_gif.py
git diff --check

Demo output includes:

MEMANTO ENGINEERING MEMORY
- Preference: Add replay tests before changing webhook behavior.
- Decision: Keep billing writes idempotent by Stripe event id.
- Quirk: Billing timestamps are stored as UTC ISO strings.
- Constraint: Do not persist raw Stripe payloads after signature verification.

Malformed-memory and atomic-write smoke check also passed with the offline backend safely recovering from an unexpected JSON shape.

Summary by CodeRabbit

  • New Features

    • New example demonstrating durable memory persistence and recall across multiple skill runs, with both local file and Memanto CLI backends.
    • Runtime bridge that injects recalled context into prompts and persists labeled engineering facts.
    • Runnable cross-skill demo and an animated demo GIF generator.
  • Documentation

    • Added comprehensive README with quick-start, run instructions, and integration pattern.
  • Tests

    • Added tests covering storage, recall ranking, metadata inclusion, executor wrapping, and recovery from malformed offline data.

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a pluggable memory backend and a SkillMemoryBridge that injects recalled memories before a skill and persists labeled memories after a skill; includes a runnable cross-skill demo, GIF generator, README, requirements, and unit tests covering recall ranking and recovery.

Changes

Claude Code Skills + Memanto Memory Bridge

Layer / File(s) Summary
Memory backend abstraction and implementations
examples/claudecode-skills-memanto/memory_backends.py
BaseMemoryBackend and MemoryRecord added. FileMemoryBackend persists JSON with atomic writes and ranks recall by token overlap. MemantoCliBackend manages memanto CLI agent lifecycle and uses the SDK for remember/recall; subprocess and utility helpers included.
Skill memory bridge integration
examples/claudecode-skills-memanto/skill_memory_bridge.py
Adds SkillRun/SkillExecution dataclasses and SkillMemoryBridge with before_skill, prompt_with_memory, run_with_memory, after_skill, and helpers for query, tags, and memory-type mapping.
Demo runner, GIF generator, and docs
examples/claudecode-skills-memanto/run_cross_skill_demo.py, examples/claudecode-skills-memanto/make_demo_gif.py, examples/claudecode-skills-memanto/README.md, examples/claudecode-skills-memanto/requirements.txt
Adds a CLI demo that runs two sequential skill sessions (store then recall) with local-file or memanto backend and reset flag; make_demo_gif.py renders an animated demo GIF; README documents hooks, quick-start, and verification.
Unit tests for bridge and backend
examples/claudecode-skills-memanto/tests/test_skill_memory_bridge.py
Unittests verify bridge stores labeled memories and recalls relevant context, FileMemoryBackend recall ranking and limit, run_with_memory behavior, metadata contribution to queries, and recovery when the on-disk JSON is malformed or unexpectedly shaped.

Sequence Diagram

sequenceDiagram
    participant Skill
    participant SkillMemoryBridge
    participant BaseMemoryBackend
    participant MemantoCliBackend
    participant FileMemoryBackend
    Skill->>SkillMemoryBridge: before_skill(SkillRun)
    SkillMemoryBridge->>SkillMemoryBridge: _query_for(run)
    SkillMemoryBridge->>BaseMemoryBackend: recall(query, limit)
    BaseMemoryBackend-->>SkillMemoryBridge: list of memories
    SkillMemoryBridge-->>Skill: formatted memory context
    Skill->>Skill: execute with context
    Skill->>SkillMemoryBridge: after_skill(run, transcript)
    SkillMemoryBridge->>SkillMemoryBridge: extract labeled lines via regex
    loop for each labeled line
        SkillMemoryBridge->>SkillMemoryBridge: _memory_type(label)
        SkillMemoryBridge->>BaseMemoryBackend: remember(content, type, tags)
    end
    BaseMemoryBackend-->>SkillMemoryBridge: persist
    SkillMemoryBridge-->>Skill: list of stored memories
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • het0814

Poem

🐰 I hopped through code with a curious cheer,

I helped memories stick from session to session here.
Decisions and quirks in tidy rows,
From grill to TDD the knowledge grows,
A little rabbit applauds this bridge so dear.

🚥 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 and concisely summarizes the main change: adding a Memanto memory bridge for Claude Code skills.
Linked Issues check ✅ Passed The PR comprehensively implements all coding objectives from issue #508: Memanto integration, lifecycle hooks (before/after), memory extraction and injection, dual backends, and reusable bridge API.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the PR objectives: the example implementation, memory backends, bridge logic, demo script, and comprehensive tests are within scope.
Docstring Coverage ✅ Passed Docstring coverage is 87.88% which is sufficient. The required threshold is 80.00%.

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

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

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 (2)
examples/claudecode-skills-memanto/memory_backends.py (1)

160-173: ⚡ Quick win

Add a timeout to the CLI subprocess call.

_run (and _ensure_agent) invoke a CLI that reaches the Moorcheh backend over the network. Without a timeout, a hung request blocks the demo indefinitely. A small timeout with a clear error keeps the example resilient.

♻️ Proposed change
 def _run(cmd: list[str], *, capture: bool = False) -> str:
     try:
         result = subprocess.run(
             cmd,
             capture_output=True,
             text=True,
             check=True,
+            timeout=30,
         )
     except OSError as exc:
         raise _missing_memanto_error() from exc
+    except subprocess.TimeoutExpired as exc:
+        raise RuntimeError("Memanto CLI command timed out") from exc
     except subprocess.CalledProcessError as exc:
🤖 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/memory_backends.py` around lines 160 -
173, The _run function (and the related _ensure_agent caller) must pass a
timeout to subprocess.run to avoid hanging; add a small sensible timeout (e.g.,
10 seconds) as the timeout arg in subprocess.run, and catch
subprocess.TimeoutExpired to raise a clear RuntimeError like "Memanto CLI
command timed out" (include any available stdout/stderr in the message); update
any callers such as _ensure_agent if they call _run without expecting timeouts
so errors propagate cleanly.
examples/claudecode-skills-memanto/requirements.txt (1)

2-2: 💤 Low value

Remove unused python-dotenv from this example
No dotenv imports or load_dotenv calls are present in examples/claudecode-skills-memanto, so python-dotenv>=1.0.0 in examples/claudecode-skills-memanto/requirements.txt can likely be dropped (unless it’s used by code outside this directory).

🤖 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/requirements.txt` at line 2, The
requirements file lists python-dotenv (python-dotenv>=1.0.0) but the example
code in examples/claudecode-skills-memanto does not import dotenv or call
load_dotenv; remove the unused dependency from
examples/claudecode-skills-memanto/requirements.txt by deleting the
python-dotenv>=1.0.0 line (or move it to a higher-level shared requirements file
if another part of the repository actually needs it), and run a quick
install/test of the example to ensure nothing else relies on python-dotenv.
🤖 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/memory_backends.py`:
- Around line 109-128: The remember method is calling the memanto CLI with
undocumented flags (--source and --tags) which can cause unrecognized-argument
errors; update the _run invocation in remember to only use supported CLI args
(keep "--type" and the content) and remove "--source" and "--tags", and if you
need to record provenance or tags attach them to the content string or use a
documented API/flag instead; locate the remember function and its _run call and
replace the unsupported flags that reference self.agent_id and tags with a
supported approach (e.g., embed provenance/tags in content or use the memanto
client/library method).
- Around line 130-139: The recall() implementation scrapes free-form memanto
stdout and filters banner lines, which is brittle; update recall to invoke
memanto via a stable, structured channel or parse a stable payload section
instead of line-based heuristics: modify the call site that uses
_run(["memanto", "recall", ...]) so it requests or extracts a machine-readable
block (e.g., detect and parse a JSON/YAML block if memanto emits one, or call a
memanto library/API instead of the CLI), then parse that structured payload into
the list[str] returned by recall(); ensure you remove the fragile
startswith("MEMANTO","Agent:") filtering and handle parsing errors with clear
exceptions in recall() so failures aren’t silently ignored.
- Around line 141-153: The current _ensure_agent falls back to running
_run(["memanto", "agent", "activate", self.agent_id]) on any non-zero return
code from subprocess.run, which can mask other failures; change it to inspect
the failed process result (the create variable from subprocess.run inside
_ensure_agent) and only call _run activate when the stderr/stdout indicates the
agent already exists (e.g., contains "already exists" or similar message),
otherwise raise an error (include create.stderr/create.stdout) so other create
failures surface; keep the existing OSError -> _missing_memanto_error behavior
intact.

In `@examples/claudecode-skills-memanto/README.md`:
- Around line 66-84: The snippet calls SkillMemoryBridge.before_skill and
after_skill with keyword args but the bridge API expects a SkillRun object;
create a SkillRun instance (e.g., run = SkillRun(skill_name="/tdd", task="Add
tests for invoice webhook idempotency", file_paths=[...])) and pass that to
bridge.before_skill(run) to get memory_context, build the prompt and call
run_skill, then call bridge.after_skill(run, result.transcript) (do not pass
file_paths to after_skill).

---

Nitpick comments:
In `@examples/claudecode-skills-memanto/memory_backends.py`:
- Around line 160-173: The _run function (and the related _ensure_agent caller)
must pass a timeout to subprocess.run to avoid hanging; add a small sensible
timeout (e.g., 10 seconds) as the timeout arg in subprocess.run, and catch
subprocess.TimeoutExpired to raise a clear RuntimeError like "Memanto CLI
command timed out" (include any available stdout/stderr in the message); update
any callers such as _ensure_agent if they call _run without expecting timeouts
so errors propagate cleanly.

In `@examples/claudecode-skills-memanto/requirements.txt`:
- Line 2: The requirements file lists python-dotenv (python-dotenv>=1.0.0) but
the example code in examples/claudecode-skills-memanto does not import dotenv or
call load_dotenv; remove the unused dependency from
examples/claudecode-skills-memanto/requirements.txt by deleting the
python-dotenv>=1.0.0 line (or move it to a higher-level shared requirements file
if another part of the repository actually needs it), and run a quick
install/test of the example to ensure nothing else relies on python-dotenv.
🪄 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: db0cfefa-162e-448a-ab88-3acf7cb66e72

📥 Commits

Reviewing files that changed from the base of the PR and between a17ebc4 and fd8db38.

⛔ Files ignored due to path filters (1)
  • examples/claudecode-skills-memanto/assets/demo.gif is excluded by !**/*.gif
📒 Files selected for processing (6)
  • examples/claudecode-skills-memanto/README.md
  • examples/claudecode-skills-memanto/make_demo_gif.py
  • examples/claudecode-skills-memanto/memory_backends.py
  • examples/claudecode-skills-memanto/requirements.txt
  • examples/claudecode-skills-memanto/run_cross_skill_demo.py
  • examples/claudecode-skills-memanto/skill_memory_bridge.py

Comment thread examples/claudecode-skills-memanto/memory_backends.py
Comment thread examples/claudecode-skills-memanto/memory_backends.py Outdated
Comment thread examples/claudecode-skills-memanto/memory_backends.py
Comment thread examples/claudecode-skills-memanto/README.md

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
examples/claudecode-skills-memanto/memory_backends.py (2)

84-88: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate the loaded JSON shape here.

json.loads(...) accepts any valid JSON. If the file contains {} or a list with non-object entries, remember() will fail on .append(...) or recall() will fail on .get(...) later. Normalize unexpected shapes to the existing warning/fallback path here.

💡 Minimal fix
     def _load(self) -> list[dict[str, str]]:
         if not self.path.exists():
             return []
         try:
-            return json.loads(self.path.read_text(encoding="utf-8"))
+            payload = json.loads(self.path.read_text(encoding="utf-8"))
+            if not isinstance(payload, list) or not all(
+                isinstance(item, dict) for item in payload
+            ):
+                raise json.JSONDecodeError("Expected a list of objects", "", 0)
+            return payload
         except json.JSONDecodeError:
             warnings.warn(
                 f"Ignoring malformed demo memory file: {self.path}",
                 RuntimeWarning,
                 stacklevel=2,
🤖 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/memory_backends.py` around lines 84 - 88,
The _load method currently returns whatever json.loads(self.path.read_text(...))
yields which can be any JSON shape; update _load to validate that the parsed
value is strictly a list of dict[str, str] (each item a mapping with string keys
and string values), and if not, log a warning and return the empty-list fallback
(or coerce safe shapes into that format) so subsequent methods like remember()
and recall() (which rely on .append and .get) never receive invalid types;
reference the _load function, remember(), and recall() when adding the
validation and warning logic and ensure the fallback path is used on any
unexpected shape.

61-71: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Write the file store atomically.

This rewrites the entire JSON file in place. If the process is interrupted mid-write, the store can become truncated, and _load() will then treat the whole history as empty on the next run. Write to a temp file in the same directory and replace() it instead.

💡 Minimal fix
     def remember(
         self,
         content: str,
         *,
         memory_type: str = "learning",
         tags: str = "claudecode,skills,memanto",
     ) -> None:
         self.path.parent.mkdir(parents=True, exist_ok=True)
         records = self._load()
         records.append(
             MemoryRecord(
                 content=content,
                 memory_type=memory_type,
                 source=self.source,
                 tags=tags,
             ).to_json()
         )
-        self.path.write_text(json.dumps(records, indent=2) + "\n", encoding="utf-8")
+        payload = json.dumps(records, indent=2) + "\n"
+        tmp_path = self.path.with_suffix(f"{self.path.suffix}.tmp")
+        tmp_path.write_text(payload, encoding="utf-8")
+        tmp_path.replace(self.path)
🤖 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/memory_backends.py` around lines 61 - 71,
The current append flow loads records via self._load(), appends a MemoryRecord
JSON and calls self.path.write_text(...) which can truncate the store if
interrupted; change the write to perform an atomic write: create a temporary
file in the same directory (e.g., using tempfile.NamedTemporaryFile or a
Path-based temp name), write json.dumps(records, indent=2) to that temp file
with utf-8 encoding, flush and fsync to disk, then atomically replace the
original file with Path.replace(temp_path, self.path). Update the code paths
that call self.path.write_text(...) to use this temp-write-and-replace approach
so _load() never sees a truncated file.
🤖 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.

Outside diff comments:
In `@examples/claudecode-skills-memanto/memory_backends.py`:
- Around line 84-88: The _load method currently returns whatever
json.loads(self.path.read_text(...)) yields which can be any JSON shape; update
_load to validate that the parsed value is strictly a list of dict[str, str]
(each item a mapping with string keys and string values), and if not, log a
warning and return the empty-list fallback (or coerce safe shapes into that
format) so subsequent methods like remember() and recall() (which rely on
.append and .get) never receive invalid types; reference the _load function,
remember(), and recall() when adding the validation and warning logic and ensure
the fallback path is used on any unexpected shape.
- Around line 61-71: The current append flow loads records via self._load(),
appends a MemoryRecord JSON and calls self.path.write_text(...) which can
truncate the store if interrupted; change the write to perform an atomic write:
create a temporary file in the same directory (e.g., using
tempfile.NamedTemporaryFile or a Path-based temp name), write
json.dumps(records, indent=2) to that temp file with utf-8 encoding, flush and
fsync to disk, then atomically replace the original file with
Path.replace(temp_path, self.path). Update the code paths that call
self.path.write_text(...) to use this temp-write-and-replace approach so _load()
never sees a truncated file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 647aeb47-9441-4367-b226-1abc46b54709

📥 Commits

Reviewing files that changed from the base of the PR and between fd8db38 and f17789d.

📒 Files selected for processing (3)
  • examples/claudecode-skills-memanto/README.md
  • examples/claudecode-skills-memanto/memory_backends.py
  • examples/claudecode-skills-memanto/requirements.txt
💤 Files with no reviewable changes (1)
  • examples/claudecode-skills-memanto/requirements.txt
✅ Files skipped from review due to trivial changes (1)
  • examples/claudecode-skills-memanto/README.md

@attaboy11

Copy link
Copy Markdown
Author

Follow-up for the review thread: I addressed the CodeRabbit findings in f17789d, 47f1d45, and 752f3bf.

What changed:

  • align the README snippet with the SkillRun API
  • remove the unused python-dotenv example dependency
  • add bounded Memanto CLI subprocess calls with clearer timeout/error handling
  • validate offline memory JSON shape before recall/append
  • write the demo memory store atomically via temp-file replacement

Validation run locally:

  • python3 -m py_compile examples/claudecode-skills-memanto/*.py
  • python3 examples/claudecode-skills-memanto/run_cross_skill_demo.py --backend file --reset
  • smoke check for malformed memory fallback and file backend hardening

@attaboy11

Copy link
Copy Markdown
Author

Added the organic social showcase link to the PR description: https://x.com/ciprianimacovei/status/2061044237206950149?s=46&t=lY3sRT0pRNlqtaJrHuIX4w

@attaboy11

Copy link
Copy Markdown
Author

Follow-up hardening pushed in 1acabd9.\n\nWhat changed:\n- added focused offline unit coverage for labeled memory extraction, recall ranking, malformed JSON recovery, and unexpected-shape JSON recovery\n- made labeled memory extraction tolerate leading whitespace in pasted/indented transcripts\n- documented the unittest verification command in the example README\n\nValidation rerun locally:\n- python3 -m unittest discover -s examples/claudecode-skills-memanto/tests -v -> 4 tests passed\n- python3 -m compileall examples/claudecode-skills-memanto -> passed\n- python3 -m ruff check ... -> passed\n- python3 examples/claudecode-skills-memanto/run_cross_skill_demo.py --backend file --reset -> still recalls the Stripe event id, replay-test preference, UTC timestamp quirk, and raw-payload constraint\n- git diff --check -> passed

@attaboy11

Copy link
Copy Markdown
Author

Follow-up hardening pushed in 08b23f6 to make the bridge more reusable/importable rather than just a demo script.

What changed:

  • added SkillMemoryBridge.run_with_memory(...), an executor-agnostic wrapper that can sit around any existing Claude Code, shell, or custom skill runner
  • added SkillExecution return metadata and SkillRun.metadata so project/framework identifiers can feed recall without changing the bridge internals
  • made the context header and base tags configurable while preserving the existing before_skill(...) / after_skill(...) hooks
  • updated README integration examples to show both direct hook usage and the drop-in wrapper path
  • added focused offline tests for wrapped execution, prompt injection, stored memories, tags, and metadata-driven recall

Validation rerun locally:

  • python3 -m unittest discover -s examples/claudecode-skills-memanto/tests -v -> 6 tests passed
  • python3 -m compileall examples/claudecode-skills-memanto -> passed
  • python3 -m ruff check examples/claudecode-skills-memanto/skill_memory_bridge.py examples/claudecode-skills-memanto/tests/test_skill_memory_bridge.py -> passed
  • git diff --check -> passed

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

🧹 Nitpick comments (1)
examples/claudecode-skills-memanto/skill_memory_bridge.py (1)

110-115: 💤 Low value

Optional: sanitize skill_name more robustly before using it as a tag.

strip("/") only trims leading/trailing slashes. A skill_name containing commas or whitespace would corrupt the comma-joined tag string built in after_skill (Line 99). The current FileMemoryBackend doesn't parse tags during recall, so this is non-functional today, but a more durable backend could mis-split tags.

♻️ Optional hardening
-        skill_tag = run.skill_name.strip("/")
+        skill_tag = run.skill_name.strip("/").replace(",", " ").strip()
🤖 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_memory_bridge.py` around lines 110 -
115, The _tags_for function currently uses run.skill_name.strip("/") which won't
prevent commas or whitespace from corrupting the comma-joined tag string built
in after_skill; update _tags_for to robustly sanitize the skill name (e.g., trim
outer whitespace/slashes, replace or remove commas and internal whitespace,
collapse multiple non-alphanumeric chars to a single safe separator like "-" or
"_" and lower-case the result, and drop empty results) before appending to
self.base_tags so tags are safe and stable across backends; locate and modify
_tags_for (and verify after_skill's tag join still expects comma-separated tags)
to return the sanitized tag tuple.
🤖 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.

Nitpick comments:
In `@examples/claudecode-skills-memanto/skill_memory_bridge.py`:
- Around line 110-115: The _tags_for function currently uses
run.skill_name.strip("/") which won't prevent commas or whitespace from
corrupting the comma-joined tag string built in after_skill; update _tags_for to
robustly sanitize the skill name (e.g., trim outer whitespace/slashes, replace
or remove commas and internal whitespace, collapse multiple non-alphanumeric
chars to a single safe separator like "-" or "_" and lower-case the result, and
drop empty results) before appending to self.base_tags so tags are safe and
stable across backends; locate and modify _tags_for (and verify after_skill's
tag join still expects comma-separated tags) to return the sanitized tag tuple.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92a1c02d-571e-419d-a8c7-f71df985a7b1

📥 Commits

Reviewing files that changed from the base of the PR and between 1acabd9 and 08b23f6.

📒 Files selected for processing (3)
  • examples/claudecode-skills-memanto/README.md
  • examples/claudecode-skills-memanto/skill_memory_bridge.py
  • examples/claudecode-skills-memanto/tests/test_skill_memory_bridge.py
✅ Files skipped from review due to trivial changes (1)
  • examples/claudecode-skills-memanto/README.md

@attaboy11

Copy link
Copy Markdown
Author

Follow-up hardening pushed in dfece30 for the latest CodeRabbit tag-sanitization note.

What changed:

  • normalize skill names before adding them to comma-joined memory tags, so spaces, slashes, or commas cannot create malformed tag strings
  • added a focused regression test for comma-safe tag storage

Validation rerun locally:

  • python3 -m unittest discover -s examples/claudecode-skills-memanto/tests -v -> 7 tests passed
  • python3 -m compileall examples/claudecode-skills-memanto -> passed
  • python3 -m ruff check examples/claudecode-skills-memanto/skill_memory_bridge.py examples/claudecode-skills-memanto/tests/test_skill_memory_bridge.py -> passed
  • python3 examples/claudecode-skills-memanto/run_cross_skill_demo.py --backend file --reset -> demo still recalls the stored Stripe memories
  • git diff --check -> passed

@attaboy11

Copy link
Copy Markdown
Author

Follow-up for CodeRabbit's tag-safety note: pushed 652e68f to sanitize skill names before adding them to comma-separated memory tags.

What changed:

  • lowercases skill names before tag storage
  • collapses non-alphanumeric runs to a single -
  • drops empty sanitized skill tags so only stable base tags are stored
  • added regression coverage for comma/whitespace/slash/punctuation-heavy names

Validation:

  • python3 -m unittest discover -s examples/claudecode-skills-memanto/tests -v -> 7 tests passed
  • python3 -m compileall examples/claudecode-skills-memanto -> passed
  • python3 -m ruff check examples/claudecode-skills-memanto/skill_memory_bridge.py examples/claudecode-skills-memanto/tests/test_skill_memory_bridge.py -> passed
  • git diff --check -> passed

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.

[BOUNTY $100] 🐜 The Memanto + mattpocock Developer Skills Challenge

1 participant