Skip to content

Add Claude Code Skills + Memanto SkillChain bridge#717

Closed
cwwjacobs wants to merge 5 commits into
moorcheh-ai:mainfrom
cwwjacobs:main
Closed

Add Claude Code Skills + Memanto SkillChain bridge#717
cwwjacobs wants to merge 5 commits into
moorcheh-ai:mainfrom
cwwjacobs:main

Conversation

@cwwjacobs

@cwwjacobs cwwjacobs commented Jun 9, 2026

Copy link
Copy Markdown

Summary

Adds a reviewer-safe examples/claudecode-skills-memanto integration 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:

3f58edf Add Memanto SkillChain demo proof

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Added a Claude Code Skills + Memanto SkillChain example with a local CLI to capture, store, and recall durable memory between skill runs, plus an optional live mode that integrates with the Memanto CLI.
  * Included a credential-free validation script to verify the example end-to-end.

* **Documentation**
  * Added README explaining setup, operating modes, validation steps, and usage notes.

* **Chores**
  * Updated ignore rules to exclude common Python artifacts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: be7000e2-6063-4eb3-9d63-3ff4ec760895

📥 Commits

Reviewing files that changed from the base of the PR and between 086e44b and 8e5e89d.

📒 Files selected for processing (1)
  • examples/claudecode-skills-memanto/skill_memory.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/claudecode-skills-memanto/skill_memory.py

📝 Walkthrough

Walkthrough

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

Changes

Memanto SkillChain Memory Example

Layer / File(s) Summary
Project setup and documentation
examples/claudecode-skills-memanto/.gitignore, examples/claudecode-skills-memanto/README.md
Git ignore patterns for Python artifacts (.skillchain/, __pycache__/, *.pyc) and complete documentation describing the memory-bridge purpose, local vs live Memanto operating modes, validation workflow, skill lifecycle (before/after subcommands), and external links.
MemoryCard dataclass and env utilities
examples/claudecode-skills-memanto/skill_memory.py
Adds MemoryCard dataclass, to_text(), now_iso(), and live_enabled() utilities for timestamps and gating live Memanto mode.
Line classification and durable extraction
examples/claudecode-skills-memanto/skill_memory.py
Keyword-heuristic classify() and durable_lines() to select, filter (secretish), truncate, and deduplicate candidate transcript lines for durable memory storage.
Local JSONL storage and recall
examples/claudecode-skills-memanto/skill_memory.py
Implements read_local(), write_local(), store_local() with dedupe key (content, source_skill, task), and recall_local() that ranks cards by word-overlap and recency.
Memanto CLI integration and CLI commands
examples/claudecode-skills-memanto/skill_memory.py
run_memanto() shells out to memanto CLI; before() assembles .skillchain/injected-context.md from recalled cards or fallback; after() extracts MemoryCards from transcripts and stores them locally or via memanto remember; main() wires subcommands.
Validation and testing
examples/claudecode-skills-memanto/validate.py
Credential-free validation script that resets local state, writes a demo transcript, runs the after then before flows, and asserts expected recall tokens before reporting PASS.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibbled lines and kept a card,
Saved a thought when skills ran hard,
Local stacks or Memanto's tide,
Before and after, context supplied,
Small hops, big recalls — memory's guard.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 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 describes the main change: adding a bridge between Claude Code Skills and Memanto SkillChain, which aligns with the primary content of the PR (new example integration with memory workflow).
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

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 commented Jun 9, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":500,"request":{"method":"PATCH","url":"https://api.github.com/repos/moorcheh-ai/memanto/issues/comments/4664352734","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- review_stack_entry_start -->\n\n[![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/moorcheh-ai/memanto/pull/717?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)\n\n<!-- review_stack_entry_end -->\n<!-- This is an auto-generated comment: review in progress by coderabbit.ai -->\n\n> [!NOTE]\n> Currently processing new changes in this PR. This may take a few minutes, please wait...\n> \n> <details>\n> <summary>⚙️ Run configuration</summary>\n> \n> **Configuration used**: defaults\n> \n> **Review profile**: CHILL\n> \n> **Plan**: Pro Plus\n> \n> **Run ID**: `fae726d1-7eb4-437d-9397-f5c824f3eaec`\n> \n> </details>\n> \n> <details>\n> <summary>📥 Commits</summary>\n> \n> Reviewing files that changed from the base of the PR and between b53ac14ffedd382d9f1a7effb46533231668e623 and 086e44b2c6d1de1708c5a1e991018b7979b9005c.\n> \n> </details>\n> \n> <details>\n> <summary>📒 Files selected for processing (4)</summary>\n> \n> * `examples/claudecode-skills-memanto/.gitignore`\n> * `examples/claudecode-skills-memanto/README.md`\n> * `examples/claudecode-skills-memanto/skill_memory.py`\n> * `examples/claudecode-skills-memanto/validate.py`\n> \n> </details>\n> \n> ```ascii\n>  _____________________________________________________________________________________________\n> < Use the power of command shells. Use the shell when graphical user interfaces don't cut it. >\n>  ---------------------------------------------------------------------------------------------\n>   \\\n>    \\   \\\n>         \\ /\\\n>         ( )\n>       .( o ).\n> ```\n\n<!-- end of auto-generated comment: review in progress by coderabbit.ai -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=moorcheh-ai/memanto&utm_content=717)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n<!-- usage_tips_start -->\n\n> [!TIP]\n> <details>\n> <summary>CodeRabbit can use TruffleHog to scan for secrets in your code with verification capabilities.</summary>\n> \n> Add a [TruffleHog config file](https://docs.trufflesecurity.com/configuration-file-reference) (e.g. trufflehog-config.yml, trufflehog.yml) to your project to customize detectors and scanning behavior. The tool runs only when a config file is present.\n> \n> </details>\n\n<!-- usage_tips_end -->"},"request":{"retryCount":3,"signal":{},"retries":3,"retryAfter":16}}}

@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: 2

🧹 Nitpick comments (3)
examples/claudecode-skills-memanto/skill_memory.py (2)

170-173: ⚖️ Poor tradeoff

Consider using batch API for live mode storage.

The current implementation makes one memanto remember CLI call per card, which can be slow for many cards. The Memanto API supports batch storage (see batch_remember in context snippets), which would be more efficient.

Note: For a demonstration example with typically small card counts (<12 per the durable_lines cap), 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 win

Improve subprocess error context.

When memanto CLI 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 value

Consider using check=True for simpler error handling.

The current pattern with check=False and manual returncode checking works but could be simplified using check=True, which will raise CalledProcessError automatically.

♻️ 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

📥 Commits

Reviewing files that changed from the base of the PR and between b53ac14 and 086e44b.

📒 Files selected for processing (4)
  • examples/claudecode-skills-memanto/.gitignore
  • examples/claudecode-skills-memanto/README.md
  • examples/claudecode-skills-memanto/skill_memory.py
  • examples/claudecode-skills-memanto/validate.py

Comment thread examples/claudecode-skills-memanto/skill_memory.py
Comment thread examples/claudecode-skills-memanto/skill_memory.py
@Xenogents

Copy link
Copy Markdown
Collaborator

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:

  • High Friction (CLI Wrappers): Many submissions used Python or Bash wrappers (e.g., forcing the user to type memanto-wrap /tdd instead of the native claude /tdd). While effective at passing context, managing child PTY processes introduces terminal overhead and breaks the developer's native muscle memory
  • Incomplete Lifecycle (Manual Scripts): Some submissions successfully implemented the context extraction logic but failed to automate it, requiring the user to manually run pre and post scripts around every skill session.

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!

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.

2 participants