Add Claude Code Skills + Memanto SkillChain bridge#717
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR adds a complete example of a Memanto SkillChain memory bridge. The new example implements a Python CLI that persists Claude Code skill outputs into memory cards and recalls relevant context before subsequent skills, supporting both local file-based storage and live Memanto integration. ChangesMemanto SkillChain Memory Example
Sequence Diagram(s)sequenceDiagram
participant User
participant skill_memory.py
participant LocalJSONL
participant MemantoCLI
User->>skill_memory.py: run `before` / `after`
alt before (recall)
skill_memory.py->>LocalJSONL: recall_local(query)
skill_memory.py->>MemantoCLI: memanto recall (if MEMANTO_LIVE)
LocalJSONL-->>skill_memory.py: recalled MemoryCard list
MemantoCLI-->>skill_memory.py: recalled MemoryCard list
skill_memory.py->>User: write `.skillchain/injected-context.md`
else after (store)
skill_memory.py->>skill_memory.py: extract durable_lines(transcript)
skill_memory.py->>LocalJSONL: store_local(new_cards) (if local)
skill_memory.py->>MemantoCLI: memanto remember (if MEMANTO_LIVE)
LocalJSONL-->>skill_memory.py: updated JSONL
MemantoCLI-->>skill_memory.py: CLI status
skill_memory.py->>User: print stored-count message
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 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)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
examples/claudecode-skills-memanto/skill_memory.py (2)
170-173: ⚖️ Poor tradeoffConsider using batch API for live mode storage.
The current implementation makes one
memanto rememberCLI call per card, which can be slow for many cards. The Memanto API supports batch storage (seebatch_rememberin context snippets), which would be more efficient.Note: For a demonstration example with typically small card counts (<12 per the
durable_linescap), the current approach is acceptable. Batch mode would require additional JSON serialization logic and error handling, so this is a low-priority optimization.🤖 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.py` around lines 170 - 173, The live mode loop calls run_memanto once per card which is inefficient; update the live_enabled() branch to use Memanto's batch API: collect the cards (using card.to_text() and card.memory_type from the cards list) into a JSON-serializable payload, call run_memanto with the batch action (e.g., "batch_remember" and the JSON string), and handle/log errors and the total stored count. Specifically modify the block that references live_enabled(), cards, run_memanto, and card.to_text()/card.memory_type to build the batch payload, perform a single run_memanto invocation, and add basic error handling and a success log.
129-133: ⚡ Quick winImprove subprocess error context.
When
memantoCLI fails, the RuntimeError doesn't include which command was attempted, making debugging harder.💡 Proposed fix to add command context
def run_memanto(args: list[str]) -> str: result = subprocess.run(["memanto", *args], text=True, capture_output=True, check=False) if result.returncode != 0: - raise RuntimeError(result.stderr.strip() or result.stdout.strip()) + cmd = " ".join(["memanto"] + args) + msg = result.stderr.strip() or result.stdout.strip() + raise RuntimeError(f"Command failed: {cmd}\n{msg}") return result.stdout.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.py` around lines 129 - 133, The RuntimeError raised in run_memanto lacks context about which command failed; update run_memanto to include the full command (the list passed to subprocess.run or its joined string), the return code, and stderr/stdout in the error message when result.returncode != 0 so callers know exactly which memanto invocation failed; locate the subprocess.run call in run_memanto and build a descriptive error string containing the command (`["memanto", *args]`), result.returncode, and result.stderr or result.stdout before raising the RuntimeError.examples/claudecode-skills-memanto/validate.py (1)
14-20: 💤 Low valueConsider using
check=Truefor simpler error handling.The current pattern with
check=Falseand manual returncode checking works but could be simplified usingcheck=True, which will raiseCalledProcessErrorautomatically.♻️ Alternative implementation
def run(args: list[str], *, stdin: str | None = None) -> str: - result = subprocess.run(args, cwd=ROOT, text=True, input=stdin, capture_output=True, check=False) - if result.returncode != 0: + try: + result = subprocess.run(args, cwd=ROOT, text=True, input=stdin, capture_output=True, check=True) + return result.stdout + except subprocess.CalledProcessError as e: - print(result.stdout) - print(result.stderr, file=sys.stderr) - raise SystemExit(result.returncode) - return result.stdout + print(e.stdout) + print(e.stderr, file=sys.stderr) + raise SystemExit(e.returncode)🤖 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/validate.py` around lines 14 - 20, The run function currently calls subprocess.run(..., check=False) and manually inspects result.returncode; change to subprocess.run(..., check=True) so CalledProcessError is raised automatically, or if you want to preserve the current behavior catch subprocess.CalledProcessError around the subprocess.run call and in the except handler print exc.output and exc.stderr (or result.stdout/result.stderr) and re-raise SystemExit(exc.returncode); update references in the run function accordingly (subprocess.run, CalledProcessError, result.stdout, result.stderr) so error printing and exit code logic remain correct but with simpler control flow.
🤖 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/skill_memory.py`:
- Around line 90-98: The read_local function can crash when LOCAL_MEMORY
contains corrupted or schema-mismatched lines because json.loads(line) or
MemoryCard(**...) may raise; wrap the per-line parsing inside a try/except in
read_local to catch exceptions from json.loads and MemoryCard construction, log
or record the offending line and error (using the existing logger or print) and
skip that line so the function returns only successfully parsed MemoryCard
instances; ensure the function still returns the cards list even if some lines
fail.
- Around line 158-169: Wrap the Path(args.transcript).read_text call in a
try/except in after(args: argparse.Namespace) to catch FileNotFoundError and
provide a clear error message (and non-zero exit) instead of letting the
traceback surface; for example, try reading the transcript, except
FileNotFoundError as e: print or log a concise message referencing
args.transcript and exit (or raise SystemExit) so downstream code that builds
MemoryCard objects via durable_lines, classify, and now_iso only runs when the
file exists.
---
Nitpick comments:
In `@examples/claudecode-skills-memanto/skill_memory.py`:
- Around line 170-173: The live mode loop calls run_memanto once per card which
is inefficient; update the live_enabled() branch to use Memanto's batch API:
collect the cards (using card.to_text() and card.memory_type from the cards
list) into a JSON-serializable payload, call run_memanto with the batch action
(e.g., "batch_remember" and the JSON string), and handle/log errors and the
total stored count. Specifically modify the block that references
live_enabled(), cards, run_memanto, and card.to_text()/card.memory_type to build
the batch payload, perform a single run_memanto invocation, and add basic error
handling and a success log.
- Around line 129-133: The RuntimeError raised in run_memanto lacks context
about which command failed; update run_memanto to include the full command (the
list passed to subprocess.run or its joined string), the return code, and
stderr/stdout in the error message when result.returncode != 0 so callers know
exactly which memanto invocation failed; locate the subprocess.run call in
run_memanto and build a descriptive error string containing the command
(`["memanto", *args]`), result.returncode, and result.stderr or result.stdout
before raising the RuntimeError.
In `@examples/claudecode-skills-memanto/validate.py`:
- Around line 14-20: The run function currently calls subprocess.run(...,
check=False) and manually inspects result.returncode; change to
subprocess.run(..., check=True) so CalledProcessError is raised automatically,
or if you want to preserve the current behavior catch
subprocess.CalledProcessError around the subprocess.run call and in the except
handler print exc.output and exc.stderr (or result.stdout/result.stderr) and
re-raise SystemExit(exc.returncode); update references in the run function
accordingly (subprocess.run, CalledProcessError, result.stdout, result.stderr)
so error printing and exit code logic remain correct but with simpler control
flow.
🪄 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: fae726d1-7eb4-437d-9397-f5c824f3eaec
📒 Files selected for processing (4)
examples/claudecode-skills-memanto/.gitignoreexamples/claudecode-skills-memanto/README.mdexamples/claudecode-skills-memanto/skill_memory.pyexamples/claudecode-skills-memanto/validate.py
|
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 reviewer-safe
examples/claudecode-skills-memantointegration for the Moorcheh / Memanto developer skills challenge.This implements a lightweight SkillChain memory bridge for Claude Code / mattpocock-style skills such as
/grill-with-docs,/tdd, and/handoff.The goal is to reduce context fragmentation between separate skill runs by capturing durable engineering decisions after one skill run and recalling relevant context before later runs.
Related bounty issue: #508
Social showcase
X: https://x.com/TerminusProto/status/2064451356392661020?s=20
Reviewer-safe demo repo
https://github.com/cwwjacobs/mdemo
The demo repo includes a reproducible proof path that does not require private API keys or network access.
Demo commit: