Skip to content

feat(claw-code): add Claw Code platform support to installer#208

Merged
illeatmyhat merged 4 commits into
mainfrom
feature/add-claw-code-support
Apr 28, 2026
Merged

feat(claw-code): add Claw Code platform support to installer#208
illeatmyhat merged 4 commits into
mainfrom
feature/add-claw-code-support

Conversation

@illeatmyhat
Copy link
Copy Markdown
Collaborator

@illeatmyhat illeatmyhat commented Apr 21, 2026

Summary

  • Adds ClawCodeInstaller class to install.sh with install, uninstall, and status methods
  • Registers claw-code in detect_platforms (detects via claw on PATH or .claw/ directory)
  • Adds claw-code to PLATFORM_CLASSES, --platform CLI choices, and all platform lists
  • Includes the platform-integrations/claw-code/plugins/evolve-lite plugin directory

Key implementation notes

  • Install uses claw plugins install <path> (local path to the bundled plugin)
  • Uninstall uses claw plugins uninstall evolve-lite@external — the @external suffix is required; the bare name is rejected by the CLI
  • Status queries claw plugins list and checks for evolve-lite in stdout

Test plan

  • bash platform-integrations/install.sh status — Claw Code section appears
  • bash platform-integrations/install.sh install --platform claw-code --dry-run — dry-run shows correct command
  • bash platform-integrations/install.sh install --platform claw-code — installs plugin via claw plugins install
  • bash platform-integrations/install.sh uninstall --platform claw-code — uninstalls via claw plugins uninstall evolve-lite@external

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added "Evolve Lite" plugin for Claw Code to capture, store, recall, publish, subscribe, sync, and export conversation-derived guidelines and preferences.
    • Automatic entity retrieval before tool use; save guideline entities and session trajectories as files.
    • Publish/unpublish and repo subscription workflows for sharing guidelines.
  • Documentation

    • Comprehensive READMEs and skill guides for learn/recall/save/save-trajectory/publish/subscribe/sync/unsubscribe workflows.
  • Chores

    • Claw Code platform added to installer/status commands.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Warning

Rate limit exceeded

@illeatmyhat has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 38 minutes and 45 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba9bf650-3987-43c5-971e-df4a5ae10a4d

📥 Commits

Reviewing files that changed from the base of the PR and between c9e4649 and bd045c3.

📒 Files selected for processing (28)
  • platform-integrations/bob/evolve-lite/skills/evolve-lite:learn/scripts/save_entities.py
  • platform-integrations/bob/evolve-lite/skills/evolve-lite:subscribe/scripts/subscribe.py
  • platform-integrations/bob/evolve-lite/skills/evolve-lite:unsubscribe/scripts/unsubscribe.py
  • platform-integrations/claude/plugins/evolve-lite/lib/config.py
  • platform-integrations/claude/plugins/evolve-lite/lib/entity_io.py
  • platform-integrations/claude/plugins/evolve-lite/skills/learn/scripts/save_entities.py
  • platform-integrations/claude/plugins/evolve-lite/skills/save-trajectory/scripts/save_trajectory.py
  • platform-integrations/claude/plugins/evolve-lite/skills/subscribe/scripts/subscribe.py
  • platform-integrations/claude/plugins/evolve-lite/skills/sync/SKILL.md
  • platform-integrations/claude/plugins/evolve-lite/skills/sync/scripts/sync.py
  • platform-integrations/claude/plugins/evolve-lite/skills/unsubscribe/SKILL.md
  • platform-integrations/claude/plugins/evolve-lite/skills/unsubscribe/scripts/unsubscribe.py
  • platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh
  • platform-integrations/claw-code/plugins/evolve-lite/lib/config.py
  • platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/learn/scripts/save_entities.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/scripts/save_trajectory.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/subscribe/scripts/subscribe.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/sync/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/sync/scripts/sync.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/unsubscribe/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/unsubscribe/scripts/unsubscribe.py
  • platform-integrations/codex/plugins/evolve-lite/skills/learn/scripts/save_entities.py
  • platform-integrations/codex/plugins/evolve-lite/skills/subscribe/scripts/subscribe.py
  • platform-integrations/codex/plugins/evolve-lite/skills/sync/scripts/sync.py
  • platform-integrations/codex/plugins/evolve-lite/skills/unsubscribe/scripts/unsubscribe.py
📝 Walkthrough

Walkthrough

Adds a new Claw Code plugin, "evolve-lite", implementing local entity storage, learn/recall/save/publish/subscribe/sync/unsubscribe skills, repo/config/audit utilities, hook-driven entity retrieval, and platform installer wiring for Claw plugin lifecycle management.

Changes

Cohort / File(s) Summary
Plugin manifest & docs
platform-integrations/claw-code/plugins/evolve-lite/.claude-plugin/plugin.json, platform-integrations/claw-code/plugins/evolve-lite/README.md
Adds plugin manifest and comprehensive README describing skills, storage layout, multi-repo sharing workflow, and install/enable steps.
Installer integration
platform-integrations/install.sh
Adds CLAW_CODE_PLUGIN and ClawCodeInstaller; extends CLI/platform dispatch to support claw-code plugin lifecycle.
Entity I/O
platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py
New core entity persistence: slug/unique filename helpers, markdown frontmatter serialization/parsing, bulk loading, atomic writes with collision avoidance, and debug logging.
Config & Audit libraries
.../lib/config.py, .../lib/audit.py
New config parser/normalizer for evolve.config.yaml (repo model, validation, read/write APIs) and append-only JSON audit logger.
Hook to invoke retrieval
platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh
PreToolUse hook script that pipes tool input to the retrieval script before tool runs.
Recall tooling
skills/recall/scripts/retrieve_entities.py, skills/recall/SKILL.md
Script loads markdown entities (including subscribed clones), annotates sources, formats printable markdown for agent consumption; SKILL.md documents hook-driven recall behavior.
Learn tooling
skills/learn/SKILL.md, skills/learn/scripts/save_entities.py
Skill spec for extracting up to 5 guideline entities; CLI script reads JSON from stdin, deduplicates, defaults metadata, and persists new entities.
Publish / Subscribe / Sync / Unsubscribe tooling
skills/publish/scripts/publish.py, skills/subscribe/scripts/subscribe.py, skills/sync/scripts/sync.py, skills/unsubscribe/scripts/unsubscribe.py, corresponding SKILL.md files
CLI scripts implement subscribe (git clone + config), publish (stamp & move guideline into write repo atomically), sync (fetch+reset or fetch+rebase per scope + delta calculation), and unsubscribe (remove config + local clone); docs describe interactive flows and edge handling.
Save-trajectory tooling
skills/save-trajectory/scripts/save_trajectory.py, skills/save-trajectory/SKILL.md
Adds trajectory JSON validation and timestamped safe write with collision handling; SKILL.md specifies trajectory envelope and usage.
Misc files
platform-integrations/claw-code/plugins/evolve-lite/skills/save/SKILL.md
Adds documentation for skill-generation workflow (skill capture and helper script generation).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Claw as Claw (Host)
    participant Hook as retrieve_entities.sh
    participant Retriever as retrieve_entities.py
    participant Entities as .evolve/entities/
    participant Claude as Claude (LLM)

    User->>Claw: Submit prompt / trigger tool
    Claw->>Hook: run PreToolUse hook
    Hook->>Retriever: pipe HOOK_TOOL_INPUT
    Retriever->>Entities: load_all_entities()
    Entities-->>Retriever: markdown entities
    Retriever->>Claw: formatted entity markdown
    Claw->>Claude: inject entities as context
    Claude->>Claude: select/filter entities → decide tool call
Loading
sequenceDiagram
    actor User
    participant Learn as learn SKILL
    participant Saver as save_entities.py
    participant Entities as .evolve/entities/
    participant FS as File system

    User->>Learn: Provide conversation
    Learn->>Saver: pipe entities JSON
    Saver->>Entities: load_all_entities()
    Entities-->>Saver: existing normalized contents
    Saver->>Saver: deduplicate incoming entities
    Saver->>FS: write_entity_file() atomic write (.tmp -> O_EXCL -> replace)
    FS-->>Saver: file written
    Saver-->>User: summary (added count, path)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • visahak
  • vinodmut

"🐰
I nibble notes from chat and store,
Hooks fetch memories from the floor,
Guidelines saved neat,
Trajectories complete,
Evolve-lite hops in, learning more!"

🚥 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 PR title clearly summarizes the main change: adding Claw Code platform support to the installer. It is concise, specific, and directly reflects the primary objective of the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 80.39% which is sufficient. The required threshold is 80.00%.
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
  • Commit unit tests in branch feature/add-claw-code-support

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

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

⚠️ Outside diff range comments (1)
platform-integrations/install.sh (1)

3-7: ⚠️ Potential issue | 🟡 Minor

Docstring/usage still lists only Bob, Claude Code, and Codex — add Claw Code.

The header comment block and the argparse description at line 1054 both advertise support for only Bob/Claude/Codex, but --platform now also accepts claw-code and the all list includes it. Low-impact but trivial and user-facing.

📝 Suggested doc sync
-# Installs Evolve Lite (and optionally Full) integrations for Bob, Claude Code, and Codex.
+# Installs Evolve Lite (and optionally Full) integrations for Bob, Claude Code, Claw Code, and Codex.
 #
 # Usage:
-#   ./install.sh install [--platform bob|claude|codex|all] [--mode lite|full] [--dir DIR] [--dry-run]
-#   ./install.sh uninstall [--platform bob|claude|codex|all] [--dir DIR] [--dry-run]
+#   ./install.sh install [--platform bob|claude|claw-code|codex|all] [--mode lite|full] [--dir DIR] [--dry-run]
+#   ./install.sh uninstall [--platform bob|claude|claw-code|codex|all] [--dir DIR] [--dry-run]
 #   ./install.sh status [--dir DIR]

And at line 1054:

-        description="Install Evolve integrations for Bob, Claude Code, and Codex.",
+        description="Install Evolve integrations for Bob, Claude Code, Claw Code, and Codex.",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@platform-integrations/install.sh` around lines 3 - 7, Update the usage header
and the argparse/platform description to include "Claw Code" (and the CLI token
"claw-code") so documentation matches the implemented options; specifically edit
the top comment block that lists supported platforms and the argparse help
string (the description around the --platform/options parsing) to mention Claw
Code and ensure the "all" list text includes claw-code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh`:
- Around line 2-11: The header comments in retrieve_entities.sh currently imply
an active PreToolUse hook (referencing HOOK_EVENT, HOOK_TOOL_NAME,
HOOK_TOOL_INPUT and saying "PreToolUse hook: retrieve relevant entities before
each tool execution"), but the manifest/README show hooks are not registered;
either register this hook in the manifest or update the comments to clarify this
is optional/manual and not automatically invoked—edit the retrieve_entities.sh
header to state that these environment variables are provided only if the
PreToolUse hook is registered (or remove the "fires before every tool call"
wording) so readers aren't misled about automatic injection.

In `@platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py`:
- Around line 258-285: The exception handler can reference an uninitialized
local variable target and raise UnboundLocalError, masking the original error;
initialize target to None before the try block (near where tempfile.mkstemp is
called) so that the except BaseException: cleanup logic (checks on target,
os.unlink of tmp_path, and removal of a 0-byte placeholder) can safely run; keep
the existing loop that assigns target via unique_filename(...) and atomic rename
via os.replace(...) but ensure target is defined as None prior to entering the
try to avoid the unbound reference.

In `@platform-integrations/claw-code/plugins/evolve-lite/README.md`:
- Around line 145-169: Update the documented plugin tree in README.md to include
the missing hooks/ directory and its script(s); specifically add a hooks/ entry
under evolve-lite/ (e.g., hooks/retrieve_entities.sh) so the printed structure
in the Plugin Structure section matches the actual package contents and
references the bundled hook script(s).

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/learn/scripts/save_entities.py`:
- Around line 41-45: The code reads new_entities = input_data.get("entities",
[]) and only checks truthiness, which allows non-list types (e.g., dict) to slip
through and later break iteration; update the validation to ensure new_entities
is a list (use isinstance(new_entities, list)), and if not, log a descriptive
error via log(...) and print to stderr then exit (same pattern used currently)
so only a list proceeds to the loop that processes entities; refer to the
new_entities variable and the existing log/print/sys.exit calls to implement
this check.
- Around line 8-16: The import fails because lib/ is not on Python's import path
when the script runs from .claw/skills/evolve-lite/; modify the top of
save_entities.py to insert the project's lib directory into sys.path before
importing entity_io so that the module and its functions (find_entities_dir,
get_default_entities_dir, load_all_entities, write_entity_file, log/_log) can be
resolved; specifically, compute the lib path relative to the script (e.g., using
__file__ and os.path) and add it to sys.path prior to the existing from
entity_io import ... line.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py`:
- Around line 28-35: The current hook env-var logging loop (uses log, hook_keys,
and os.environ) prints full values which can leak sensitive data such as
HOOK_TOOL_INPUT; change it to only log keys and either a redacted placeholder or
safe metadata (e.g., "<redacted>" or value length/type) for sensitive names
(specifically HOOK_TOOL_INPUT and any keys containing "TOOL_INPUT", "SECRET",
"PASSWORD", or "KEY"); keep non-sensitive keys readable if desired but avoid
printing full content for any key that matches those patterns or a configurable
sensitive set.
- Around line 16-20: The import of entity_io fails when the script is executed
directly because lib/ isn't on sys.path; update the top of the module so that
before importing entity_io you compute the plugin root (e.g., from the script's
__file__ parent directories), prepend the plugin's lib directory to sys.path,
then import entity_io and its symbols (find_entities_dir, load_all_entities,
log). Ensure this change is placed above the existing import line so functions
like find_entities_dir/load_all_entities and any uses in main() can be resolved
at runtime.

In `@platform-integrations/claw-code/plugins/evolve-lite/skills/recall/SKILL.md`:
- Around line 3-19: The docs claim recall runs automatically via hooks and reads
a JSON prompt from stdin, which conflicts with the current Claw integration
being manual; update the "Entity Retrieval" section (and the numbered steps
under "How It Works") to either (A) state that recall is manually invoked and
describe the manual invocation flow and expected stdin/json format, or (B) add
the missing hook registration details including the hook name, where to register
it, and the behavior of the recall script (reading a JSON payload with a
`prompt` field from stdin, loading entities from `.evolve/entities/`, and
writing formatted entities to stdout) so the documentation and the actual
implementation (references: the "Entity Retrieval" section title and the
numbered steps 1–5) are consistent.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/scripts/save_trajectory.py`:
- Around line 58-73: The generate_filename function currently races by checking
candidate.exists() then creating the file later; change it to atomically claim a
filename by attempting to create the file with os.open(..., os.O_CREAT |
os.O_EXCL | os.O_WRONLY) inside the initial check and inside the suffix loop (in
generate_filename and the similar block around lines 110-118), closing the
returned fd and returning the Path on success; if os.open raises
FileExistsError, continue to the next suffix, and only raise RuntimeError after
exhausting suffixes. Ensure os is imported and use the same base_name/candidate
logic but replace exists() checks with atomic os.open attempts.
- Around line 102-107: The current validation only checks truthiness of messages
from trajectory.get("messages") so non-list types like a non-empty string or
object can pass; change the check to ensure messages is an instance of list and
has length > 0 (e.g., validate with isinstance(messages, list) and len(messages)
> 0) before proceeding, and if that fails use the existing log/print/exit
behavior; update references to the messages variable and the
trajectory.get("messages", []) usage in save_trajectory.py to perform this
stricter validation.
- Around line 46-55: The get_trajectories_dir function ignores the EVOLVE_DIR
env var; update it to prefer EVOLVE_DIR (if set and non-empty) as the base
directory, falling back to CLAUDE_PROJECT_ROOT (when present) and then to the
existing default (./.evolve/trajectories); ensure you construct the Path from
EVOLVE_DIR and append "trajectories" when appropriate, call
base.mkdir(parents=True, exist_ok=True, mode=0o700) and return base.resolve() as
before.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/SKILL.md`:
- Around line 110-134: Remove the duplicated "### Step 5: Save via Helper
Script" block that contains the hardcoded $HOME one-liner; keep the second, more
robust snippet that computes real_home via pwd.getpwuid(...) and honors
CLAW_CONFIG_HOME (the version that sets real_home, config_home, script, and runs
python3 "$script" "$tmp"). Delete the earlier duplicate heading, its hardcoded
one-liner (the snippet using script="$HOME/.claw/..."), and the repeated
"Important" paragraph so only a single Step 5 with the CLAW_CONFIG_HOME-aware
invocation remains; ensure the tmp and script variables and the trap line are
preserved from the kept snippet.

---

Outside diff comments:
In `@platform-integrations/install.sh`:
- Around line 3-7: Update the usage header and the argparse/platform description
to include "Claw Code" (and the CLI token "claw-code") so documentation matches
the implemented options; specifically edit the top comment block that lists
supported platforms and the argparse help string (the description around the
--platform/options parsing) to mention Claw Code and ensure the "all" list text
includes claw-code.
🪄 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

Run ID: 6e0cf944-dbac-44fe-8b32-714342dad7a1

📥 Commits

Reviewing files that changed from the base of the PR and between 6f79732 and da91792.

📒 Files selected for processing (13)
  • platform-integrations/claw-code/plugins/evolve-lite/.claude-plugin/plugin.json
  • platform-integrations/claw-code/plugins/evolve-lite/README.md
  • platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh
  • platform-integrations/claw-code/plugins/evolve-lite/lib/__init__.py
  • platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/learn/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/learn/scripts/save_entities.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/recall/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/scripts/save_trajectory.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save/SKILL.md
  • platform-integrations/install.sh

Comment thread platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh Outdated
Comment thread platform-integrations/claw-code/plugins/evolve-lite/README.md
Comment thread platform-integrations/claw-code/plugins/evolve-lite/skills/recall/SKILL.md Outdated
illeatmyhat and others added 2 commits April 28, 2026 12:47
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bring claw-code's evolve-lite plugin up to parity with claude's after
rebase: port post-rebase updates to learn/recall/save/save-trajectory,
add the publish/subscribe/sync/unsubscribe sharing skills, and sync
shared lib/ (audit.py, config.py, entity_io.py). SKILL.md command
examples are adapted to claw's sh -lc path-resolution pattern instead
of \${CLAUDE_PLUGIN_ROOT}.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@illeatmyhat illeatmyhat force-pushed the feature/add-claw-code-support branch from da91792 to c9e4649 Compare April 28, 2026 19:58
- claw-code retrieve_entities.sh: clarify the PreToolUse hook is optional
  and not auto-registered by the packaged plugin
- entity_io.write_entity_file: initialize target=None so the except handler
  can't raise UnboundLocalError (claude + claw-code)
- save_entities.py: reject malformed payloads where `entities` is not a
  list (claude + claw-code + codex + bob)
- claw-code recall retrieve_entities.py: redact HOOK_*/CLAWD_* env values
  (HOOK_TOOL_INPUT may carry prompts/secrets); only HOOK_EVENT and
  HOOK_TOOL_NAME remain logged verbatim
- save_trajectory.py: prefer EVOLVE_DIR over CLAUDE_PROJECT_ROOT (matches
  the documented contract); claim trajectory filenames atomically with
  O_CREAT|O_EXCL to survive same-second races; require `messages` to be
  a non-empty list instead of accepting any truthy value (claude + claw-code)
- claw-code save-trajectory/SKILL.md: drop the duplicate Step 5 block —
  keep only the CLAW_CONFIG_HOME-aware variant

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

♻️ Duplicate comments (5)
platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh (1)

2-11: ⚠️ Potential issue | 🟡 Minor

Mark this as optional unless the hook is registered.

The header still says this runs before every tool call and injects context automatically, but the current Claw packaging says hooks are not enabled by default. Reword this as an optional PreToolUse hook or register it explicitly.

📝 Suggested wording
-# PreToolUse hook: retrieve relevant entities before each tool execution.
+# Optional PreToolUse hook: retrieve relevant entities before tool execution.
 #
-# In claw-code, PreToolUse is the closest equivalent to Claude Code's
-# UserPromptSubmit hook. It fires before every tool call, injecting stored
-# guidelines and preferences from the evolve-lite entity store into context.
+# If registered by a Claw hook configuration, this script can retrieve stored
+# guidelines and preferences from the evolve-lite entity store before tool calls.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh`
around lines 2 - 11, The header in retrieve_entities.sh incorrectly claims the
script runs before every tool call by default; update the top-of-file
documentation (the comments referencing PreToolUse and the Claw-code hook
environment variables HOOK_EVENT, HOOK_TOOL_NAME, HOOK_TOOL_INPUT) to state this
is an optional PreToolUse hook that only runs if the hook is registered (or add
instructions to register it explicitly), and adjust wording to remove the
assertion that it injects context automatically on every tool call unless hooks
are enabled.
platform-integrations/claw-code/plugins/evolve-lite/skills/recall/SKILL.md (1)

3-21: ⚠️ Potential issue | 🟡 Minor

Align the recall docs with the manual Claw flow.

This still describes automatic hook-driven injection, but the packaged Claw flow is manual. Either document the registration point or rephrase the workflow as user-invoked recall.

📝 Suggested wording
-description: Retrieves relevant entities from a knowledge base. Designed to be invoked automatically via hooks to inject context-appropriate entities before task execution.
+description: Retrieves relevant entities from a knowledge base for manual review before or during task execution.
@@
-1. The PreToolUse hook fires before each tool call
-2. Script reads tool input from stdin (best-effort, ignored beyond logging)
+1. If registered, the PreToolUse hook fires before each tool call
+2. The script reads tool input from stdin (best-effort, ignored beyond logging)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@platform-integrations/claw-code/plugins/evolve-lite/skills/recall/SKILL.md`
around lines 3 - 21, The docs in SKILL.md describe automatic hook-driven
injection (PreToolUse) but the packaged Claw flow is manual; update the README
to either (A) document the registration point where the recall skill is wired
into the Claw flow (mention the PreToolUse hook and how to register/invoke the
skill) or (B) rephrase the "How It Works" steps to state that recall is
user-invoked in the packaged flow (change steps 1–5 to reflect manual invocation
and when the script should be run), and keep references to the entities path
`.evolve/entities/` and the PreToolUse hook so readers can locate the code.
platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/SKILL.md (1)

110-134: ⚠️ Potential issue | 🟡 Minor

Remove the duplicate Step 5 block.

The first shell snippet hardcodes $HOME, while the second one is the more robust CLAW_CONFIG_HOME-aware version. Keeping both leaves conflicting instructions and triggers MD024.

♻️ Suggested cleanup
-### Step 5: Save via Helper Script
-
-Write the trajectory JSON to a temporary file using the **Write** tool, then pass the file path to the helper script:
-
-1. Write the JSON to `.evolve/tmp/trajectory_input.json` using the Write tool (create the directory if needed)
-2. Run the helper script with the file path as an argument:
-
-```bash
-tmp=.evolve/tmp/trajectory_input.json; mkdir -p .evolve/tmp; trap 'rm -f "$tmp"' EXIT; script=".claw/skills/evolve-lite:save-trajectory/scripts/save_trajectory.py"; [ -f "$script" ] || script="$HOME/.claw/skills/evolve-lite:save-trajectory/scripts/save_trajectory.py"; python3 "$script" "$tmp"
-```
-
-**Important**: Do NOT use inline Python scripts, heredocs, or stdin piping to pass the trajectory JSON. Always use the Write tool to create a temp file first. This avoids escaping issues with backslashes, quotes, and newlines in conversation content.
-
 ### Step 5: Save via Helper Script
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/SKILL.md`
around lines 110 - 134, Remove the duplicated "Step 5: Save via Helper Script"
block and keep only the robust shell snippet that uses real_home and
CLAW_CONFIG_HOME (the version with real_home="$(python3 -c "import os,pwd;
print(pwd.getpwuid(os.getuid()).pw_dir")" and
config_home="${CLAW_CONFIG_HOME:-$real_home/.claw}"). Delete the earlier snippet
that hardcodes $HOME and the extra repeated "Important" paragraph so the file
contains a single clear Step 5 heading followed by the CLAW_CONFIG_HOME-aware
command and the existing warning about using the Write tool.
platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py (1)

271-296: ⚠️ Potential issue | 🔴 Critical

Initialize target before try to prevent cleanup-time UnboundLocalError.

If an exception occurs before Line 279 assigns target, Line 295 can raise a new error and hide the original failure.

Suggested fix
     # Write to a unique temp file first (avoids predictable .tmp collisions)
     fd, tmp_path = tempfile.mkstemp(dir=type_dir, suffix=".tmp", prefix=slug)
+    target = None
     try:
         os.write(fd, content.encode("utf-8"))
@@
-        if target and os.path.exists(str(target)) and os.path.getsize(str(target)) == 0:
+        if target and os.path.exists(str(target)) and os.path.getsize(str(target)) == 0:
             os.unlink(str(target))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py` around
lines 271 - 296, The cleanup path can raise UnboundLocalError because target may
not be assigned before the try block; initialize target = None before the try
and update the cleanup guard to check "if target is not None and
os.path.exists(str(target)) and os.path.getsize(str(target)) == 0:" so the code
that deletes the 0-byte placeholder only runs when a target was actually
created; keep existing logic around fd, tmp_path, unique_filename(...) and
os.replace(...) unchanged.
platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py (1)

35-38: ⚠️ Potential issue | 🟠 Major

Redact sensitive hook env values from logs.

Line 37 logs full values for all HOOK_*/CLAWD_* variables; this can expose prompts/tool input/secrets in debug logs.

Suggested fix
 hook_keys = [k for k in os.environ if k.startswith(("HOOK_", "CLAWD_"))]
 for key in sorted(hook_keys):
-    log(f"  {key}={os.environ[key]}")
+    sensitive = (
+        key == "HOOK_TOOL_INPUT"
+        or "TOOL_INPUT" in key
+        or "SECRET" in key
+        or "PASSWORD" in key
+        or key.endswith("_KEY")
+    )
+    if sensitive:
+        log(f"  {key}=<redacted>")
+    else:
+        log(f"  {key}={os.environ[key]}")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py`
around lines 35 - 38, The loop that logs environment hook values exposes
secrets: update the section that builds hook_keys and the for loop over
sorted(hook_keys) to redact values before logging (e.g., log only the key with a
masked value like "<redacted>" or a safe partial such as first/last N chars), so
change the log(f"  {key}={os.environ[key]}") usage in this block to a version
that does not emit full os.environ[key] contents; keep hook_keys, sorting, and
log() calls but pass the sanitized/masked value instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@platform-integrations/claw-code/plugins/evolve-lite/lib/config.py`:
- Around line 177-207: The _cast function is unquoting YAML scalar strings then
still coercing them to bool/number/null; detect when the original input was
quoted and in that case avoid further casting: inside _cast record a flag (e.g.,
was_quoted) before you strip quotes (currently done at start), unescape
single-quote behavior as you already do, and if was_quoted simply return the
stripped string (including the special-case of quoted empty string returning
""), otherwise proceed with the existing boolean/null/int/float/list coercion
logic; reference the existing _cast function and its quoted-handling block to
implement this early-return behavior.
- Around line 330-361: The _coerce_repo function currently accepts any non-empty
name string; update it to enforce a safe-name validation (reject names
containing path separators like "/" or "\" or traversal segments like "." or
"..", and allow only a constrained charset such as alphanumerics, underscores,
hyphens, and dots) before returning the repo dict and return None on validation
failure; locate _coerce_repo and add a validation step after name =
entry.get("name") that trims the name, checks the pattern/segments, and rejects
unsafe names (or call an existing helper like safe_name/sanitize_name if
available) so downstream path construction cannot be exploited.

In `@platform-integrations/claw-code/plugins/evolve-lite/README.md`:
- Around line 202-208: The README incorrectly states EVOLVE_DIR overrides both
entity and trajectory storage; update the text to clarify that EVOLVE_DIR only
overrides entity storage and that trajectories are derived from
CLAUDE_PROJECT_ROOT by save_trajectory.py and stored under the project's
.evolve/trajectories (i.e., mention CLAUDE_PROJECT_ROOT and save_trajectory.py
explicitly), so readers know trajectories are not redirected by EVOLVE_DIR.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py`:
- Around line 117-119: The code calls list(input_data.keys()) after
json.loads(raw) without ensuring the parsed JSON is an object; guard this by
checking the parsed value (input_data) is a dict before calling .keys() and log
a safe representation otherwise (e.g., log the type or the value), or wrap the
keys() usage in a conditional/try to avoid AttributeError; update the block
around json.loads(raw), input_data, and the log call to perform an
isinstance(input_data, dict) check and handle non-dict JSON gracefully.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/subscribe/scripts/subscribe.py`:
- Around line 95-99: The git clone call using subprocess.run (clone_cmd built
from args.remote, args.branch, args.scope and dest) can hang or raise
CalledProcessError and leave a partial clone; wrap subprocess.run in a
try/except that passes a timeout (e.g., GIT_CLONE_TIMEOUT constant) to
subprocess.run, catch subprocess.TimeoutExpired and
subprocess.CalledProcessError, and on those failures clean up the
partially-created dest directory (use shutil.rmtree if dest exists) before
surfacing a clear CLI-friendly error via logging or a raised exception; ensure
you reference and use the existing clone_cmd, args.branch, args.remote and
args.scope when re-running or reporting the failure.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/sync/scripts/sync.py`:
- Around line 44-53: The _head_hash function calls subprocess.run for "git
rev-parse HEAD" but doesn't catch subprocess.TimeoutExpired, so a git timeout
can abort the entire sync; modify _head_hash to wrap the subprocess.run call in
a try/except that catches subprocess.TimeoutExpired (and optionally OSError) and
returns None on timeout/error, mirroring the behavior in _git, and keep using
result.returncode check and result.stdout.strip() when successful to locate and
handle failures safely.
- Around line 140-143: The --config branch passes filepath= to load_config but
load_config expects project_root, causing a TypeError; change the call to pass
the config path as the project_root parameter (e.g., replace
load_config(filepath=args.config) with load_config(project_root=args.config) or
simply load_config(args.config)) so both branches call load_config with the
correct argument (referencing args.config, load_config, and cfg).

In `@platform-integrations/claw-code/plugins/evolve-lite/skills/sync/SKILL.md`:
- Around line 25-31: The two separate blockquote examples—one starting with
"Synced 2 repo(s): memory [write]..." and the next "No subscriptions configured.
Add one with /evolve-lite:subscribe..."—include an extra blank line between them
which triggers MD028; remove that blank line so the quoted examples form a
contiguous block, or alternatively convert both examples into a single fenced
code block to preserve formatting without an empty line.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/unsubscribe/scripts/unsubscribe.py`:
- Around line 59-83: The removal logic currently deletes the repo clone
(shutil.rmtree(dest)) as soon as the name matches without checking the repo's
scope; update unsubscribe flow (in unsubscribe.py around the code that builds
new_repos and deletes dest) to detect the matched repo's scope (e.g., inspect
the matched repo dict in repos for a "scope" or "permission" field) and, if it
is write-scope, require explicit confirmation or a --force flag before calling
shutil.rmtree(dest) (prompt the user or check a parsed force boolean), otherwise
skip deletion but still remove the subscription from cfg; ensure set_repos(cfg,
new_repos), save_config(cfg, project_root) and audit_append(...) remain correct
and only run after confirmation/forced deletion decisions.

---

Duplicate comments:
In
`@platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh`:
- Around line 2-11: The header in retrieve_entities.sh incorrectly claims the
script runs before every tool call by default; update the top-of-file
documentation (the comments referencing PreToolUse and the Claw-code hook
environment variables HOOK_EVENT, HOOK_TOOL_NAME, HOOK_TOOL_INPUT) to state this
is an optional PreToolUse hook that only runs if the hook is registered (or add
instructions to register it explicitly), and adjust wording to remove the
assertion that it injects context automatically on every tool call unless hooks
are enabled.

In `@platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py`:
- Around line 271-296: The cleanup path can raise UnboundLocalError because
target may not be assigned before the try block; initialize target = None before
the try and update the cleanup guard to check "if target is not None and
os.path.exists(str(target)) and os.path.getsize(str(target)) == 0:" so the code
that deletes the 0-byte placeholder only runs when a target was actually
created; keep existing logic around fd, tmp_path, unique_filename(...) and
os.replace(...) unchanged.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py`:
- Around line 35-38: The loop that logs environment hook values exposes secrets:
update the section that builds hook_keys and the for loop over sorted(hook_keys)
to redact values before logging (e.g., log only the key with a masked value like
"<redacted>" or a safe partial such as first/last N chars), so change the log(f"
{key}={os.environ[key]}") usage in this block to a version that does not emit
full os.environ[key] contents; keep hook_keys, sorting, and log() calls but pass
the sanitized/masked value instead.

In `@platform-integrations/claw-code/plugins/evolve-lite/skills/recall/SKILL.md`:
- Around line 3-21: The docs in SKILL.md describe automatic hook-driven
injection (PreToolUse) but the packaged Claw flow is manual; update the README
to either (A) document the registration point where the recall skill is wired
into the Claw flow (mention the PreToolUse hook and how to register/invoke the
skill) or (B) rephrase the "How It Works" steps to state that recall is
user-invoked in the packaged flow (change steps 1–5 to reflect manual invocation
and when the script should be run), and keep references to the entities path
`.evolve/entities/` and the PreToolUse hook so readers can locate the code.

In
`@platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/SKILL.md`:
- Around line 110-134: Remove the duplicated "Step 5: Save via Helper Script"
block and keep only the robust shell snippet that uses real_home and
CLAW_CONFIG_HOME (the version with real_home="$(python3 -c "import os,pwd;
print(pwd.getpwuid(os.getuid()).pw_dir")" and
config_home="${CLAW_CONFIG_HOME:-$real_home/.claw}"). Delete the earlier snippet
that hardcodes $HOME and the extra repeated "Important" paragraph so the file
contains a single clear Step 5 heading followed by the CLAW_CONFIG_HOME-aware
command and the existing warning about using the Write tool.
🪄 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

Run ID: 372a0c68-865b-44df-8fc5-bdbc8f8c0fcf

📥 Commits

Reviewing files that changed from the base of the PR and between da91792 and c9e4649.

📒 Files selected for processing (23)
  • platform-integrations/claw-code/plugins/evolve-lite/.claude-plugin/plugin.json
  • platform-integrations/claw-code/plugins/evolve-lite/README.md
  • platform-integrations/claw-code/plugins/evolve-lite/hooks/retrieve_entities.sh
  • platform-integrations/claw-code/plugins/evolve-lite/lib/__init__.py
  • platform-integrations/claw-code/plugins/evolve-lite/lib/audit.py
  • platform-integrations/claw-code/plugins/evolve-lite/lib/config.py
  • platform-integrations/claw-code/plugins/evolve-lite/lib/entity_io.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/learn/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/learn/scripts/save_entities.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/publish/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/publish/scripts/publish.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/recall/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/recall/scripts/retrieve_entities.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/scripts/save_trajectory.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/subscribe/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/subscribe/scripts/subscribe.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/sync/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/sync/scripts/sync.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/unsubscribe/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/unsubscribe/scripts/unsubscribe.py
  • platform-integrations/install.sh
✅ Files skipped from review due to trivial changes (6)
  • platform-integrations/claw-code/plugins/evolve-lite/.claude-plugin/plugin.json
  • platform-integrations/claw-code/plugins/evolve-lite/skills/publish/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/subscribe/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/learn/SKILL.md
  • platform-integrations/claw-code/plugins/evolve-lite/skills/unsubscribe/SKILL.md
  • platform-integrations/install.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • platform-integrations/claw-code/plugins/evolve-lite/skills/save-trajectory/scripts/save_trajectory.py
  • platform-integrations/claw-code/plugins/evolve-lite/skills/learn/scripts/save_entities.py

Comment thread platform-integrations/claw-code/plugins/evolve-lite/lib/config.py
Comment thread platform-integrations/claw-code/plugins/evolve-lite/lib/config.py
Comment on lines +202 to +208
This plugin uses a few simple storage locations:

- `.evolve/entities/` for saved guidance entities
- `.evolve/trajectories/` for exported conversation trajectories
- `.claw/skills/` or `~/.claw/skills/` for installed/generated skills

If `EVOLVE_DIR` is set, entity and trajectory storage follows that override instead of the default `.evolve/` directory.
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

Clarify that EVOLVE_DIR does not redirect trajectories here.

save_trajectory.py derives .evolve/trajectories from CLAUDE_PROJECT_ROOT, not EVOLVE_DIR. As written, this note suggests both entities and trajectories follow the override, which is inaccurate.

📝 Suggested wording
-If `EVOLVE_DIR` is set, entity and trajectory storage follows that override instead of the default `.evolve/` directory.
+`EVOLVE_DIR` controls entity storage; trajectory export still follows `CLAUDE_PROJECT_ROOT` via the helper script.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@platform-integrations/claw-code/plugins/evolve-lite/README.md` around lines
202 - 208, The README incorrectly states EVOLVE_DIR overrides both entity and
trajectory storage; update the text to clarify that EVOLVE_DIR only overrides
entity storage and that trajectories are derived from CLAUDE_PROJECT_ROOT by
save_trajectory.py and stored under the project's .evolve/trajectories (i.e.,
mention CLAUDE_PROJECT_ROOT and save_trajectory.py explicitly), so readers know
trajectories are not redirected by EVOLVE_DIR.

- config._cast: quoted YAML scalars stay strings — only unquoted scalars
  coerce to bool/null/int/float/list (claude + claw-code)
- config._coerce_repo: reject names that fail is_valid_repo_name so a
  hand-edited evolve.config.yaml can't smuggle path traversal into
  downstream clone paths (claude + claw-code)
- claw-code recall retrieve_entities.py: guard input_data type before
  calling .keys(); non-dict JSON no longer aborts recall
- subscribe clone: wrap subprocess.run with timeout + capture_output and
  clean up the partial dest directory on failure (claude + claw-code +
  codex + bob)
- sync._head_hash: route through the existing _git helper so
  subprocess.TimeoutExpired no longer aborts the whole sync run
  (claude + claw-code)
- sync --config: load_config takes project_root, not filepath — the
  prior call raised TypeError on every --config usage. Resolve the path
  to its parent and pass project_root (claude + claw-code + codex)
- unsubscribe: add --force; refuse to delete a write-scope clone without
  it (the clone may hold unpushed publish commits). SKILL.md updated to
  surface the flag for the agent. (claude + claw-code + codex + bob)
- claw-code sync/SKILL.md and claude sync/SKILL.md: collapse the two
  example blockquotes into one block (markdownlint MD028)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@illeatmyhat illeatmyhat merged commit e9ba82a into main Apr 28, 2026
7 of 8 checks passed
@visahak visahak deleted the feature/add-claw-code-support branch April 28, 2026 20:27
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