Skip to content

feat: add funding-digest skill + OpenClaw compatibility#15

Open
brunodmsi wants to merge 1 commit into
mainfrom
feat/funding-digest-and-openclaw
Open

feat: add funding-digest skill + OpenClaw compatibility#15
brunodmsi wants to merge 1 commit into
mainfrom
feat/funding-digest-and-openclaw

Conversation

@brunodmsi

@brunodmsi brunodmsi commented Mar 16, 2026

Copy link
Copy Markdown
Member

Summary

  • New funding-digest skill: weekly digest of new funding programs added to the Karma Funding Map in the past 7 days. Supports user preference filters (ecosystem, type, topic, budget) stored in platform-native memory (CLAUDE.md / USER.md). Includes cron setup for both Claude Code (CronCreate) and OpenClaw (cron.add with delivery to Slack/Telegram/Discord)
  • Optimized find-funding-opportunities (v1.2.0 → v1.3.0): ecosystem queries now run community lookup + ecosystems= + name= searches in parallel in a single bash call, then resolve communityUid sequentially. Cuts agent roundtrips from 3-4 to 1-2 while keeping the community list fresh
  • Flattened metadata in all SKILL.md files to single-line JSON (metadata: {"author": "Karma", ...}) for OpenClaw parser compatibility. Claude Code is unaffected — it only uses name, description, version, tags from frontmatter

Test plan

  • Run find-funding-opportunities with an ecosystem query (e.g., "grants on Optimism") and verify parallel queries return merged, deduplicated results
  • Run find-funding-opportunities without ecosystem (e.g., "hackathons") and verify single-request path works
  • Run funding-digest manually ("show me new funding this week") and verify digest output
  • Set a preference ("only ping me about AI programs") and verify it persists and filters subsequent runs
  • Verify all existing skills still load correctly with flattened metadata on Claude Code
  • Test clawhub publish with flattened metadata format

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced Funding Digest plugin (v0.1.0) for weekly funding opportunity digests with support for user preference filters and scheduled execution.
  • Updates

    • Updated Find Funding Opportunities plugin to v1.3.0 with improved workflow documentation and refined API reference.

…n metadata for OpenClaw

- New funding-digest skill: weekly digest of new programs with user preference
  filters (ecosystem, type, topic, budget) and cron setup for both Claude Code
  (CronCreate) and OpenClaw (cron.add with delivery channels)
- Optimize find-funding-opportunities (v1.3.0): run community lookup + ecosystem
  + name queries in parallel in a single bash call instead of 3-4 sequential
  agent roundtrips
- Flatten metadata in all SKILL.md files to single-line JSON for OpenClaw parser
  compatibility while maintaining Claude Code support
- Update marketplace.json and README with new skill

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces the new Funding Digest plugin to the marketplace, bumps Find Funding Opportunities to version 1.3.0, adds comprehensive documentation for the funding-digest skill, standardizes metadata formatting across skill files from YAML to JSON, and refactors find-funding-opportunities documentation to emphasize parallel execution.

Changes

Cohort / File(s) Summary
Plugin Registry & Marketplace
.claude-plugin/marketplace.json
Added new Funding Digest plugin (v0.1.0) with discovery and digest tags; bumped Find Funding Opportunities version to 1.3.0.
Funding Digest Skill
skills/funding-digest/SKILL.md, README.md
Introduced new skill document with four-step workflow for weekly funding digests, including user preference persistence, API queries, result formatting, and cron setup; added corresponding README entry.
Find Funding Opportunities Refactor
skills/find-funding-opportunities/SKILL.md, skills/find-funding-opportunities/references/api-reference.md
Refactored documentation from sequential multi-step to parallel execution approach; simplified examples and result formatting; consolidated field mappings; updated version to 1.3.0 and metadata format; adjusted X-Invocation-Id header description (4 to 3 curl calls).
Metadata Standardization
.claude/skills/skill-creator/SKILL.md, skills/project-manager/SKILL.md, skills/setup-agent/SKILL.md, skills/skill-creator/SKILL.md
Converted metadata declarations from YAML multi-line mappings to single-line JSON format across four skill files.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

🐰 A digest arrives for funding dreams,
With metadata neat in JSON streams,
Parallel paths now faster flow,
New skills bloom where rabbits go! ✨💰

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main changes: adding a new funding-digest skill and OpenClaw compatibility support.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/funding-digest-and-openclaw
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

You can make CodeRabbit's review stricter and more nitpicky using the `assertive` profile, if that's what you prefer.

Change the reviews.profile setting to assertive to make CodeRabbit's nitpick more issues in your PRs.

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

🧹 Nitpick comments (2)
skills/funding-digest/SKILL.md (1)

75-88: Consider adding language specifiers to fenced code blocks.

Static analysis flagged these template blocks as missing language specifiers. For the output format templates (lines 75-88, 94-100), consider using markdown since they represent formatted output. For the cron schedule example (lines 114-117), plain text is acceptable but could use text for explicitness.

📝 Proposed fix
-```
+```markdown
 # Funding Digest — Week of {Mon DD}
-```
+```markdown
 # Funding Digest — Week of {Mon DD}
 
 No new programs added this week{preference_summary}.
-```
+```text
 Schedule: 0 9 * * 1
 Prompt: Run the funding-digest skill — fetch and display new funding opportunities from the past week

Also applies to: 94-100, 114-117

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/funding-digest/SKILL.md` around lines 75 - 88, Update the fenced code
blocks in SKILL.md to include language specifiers: add ```markdown for the
output-format templates that start with the header "Funding Digest — Week of
{Mon DD}" (both the filled and "No new programs" variants referenced around
lines 75-100) and use ```text for the cron schedule block that contains
"Schedule: 0 9 * * 1" (the example at ~114-117); ensure every triple-backtick
fence in those examples is annotated accordingly so static analyzers recognize
the block language.
skills/find-funding-opportunities/SKILL.md (1)

118-118: Style: Avoid spaces at boundaries of inline code.

Line 118 contains `, ` (comma-space in backticks). Consider removing the backticks and describing it as "comma-separated" or using `,` without the trailing space for cleaner markdown.

✨ Suggested improvement
-- **Ecosystem**: `metadata.ecosystems` joined with `, ` (fall back to `communities[0].name`)
+- **Ecosystem**: `metadata.ecosystems` joined with `,` (comma-separated) or fall back to `communities[0].name`

As per static analysis hints: "Spaces inside code span elements (MD038)."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/find-funding-opportunities/SKILL.md` at line 118, Update the inline
code in the Ecosystem line to avoid spaces inside code spans: replace the
backticked "`, ` " with either a description like "comma-separated" or a
backticked comma without the trailing space (e.g., change the fragment in the
line that reads "**Ecosystem**: `metadata.ecosystems` joined with `, ` (fall
back to `communities[0].name`)” so the separator is written as "comma-separated"
or `` `,` ``), ensuring no spaces inside the code span.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@skills/find-funding-opportunities/SKILL.md`:
- Around line 104-113: The fenced code block containing the output template
starting with "Found {count} programs (showing top 10):" in SKILL.md is missing
a language specifier; update the opening fence to include a language (e.g.,
change ``` to ```text or ```markdown) so the block becomes labeled (this
addresses MD040 and improves rendering/accessibility for the template output
shown in the Find Funding Opportunities skill).
- Around line 65-68: The curl commands write to fixed temp files
(/tmp/kf_communities.json, /tmp/kf_eco.json, /tmp/kf_name.json) causing race
conditions; change them to write into a unique temp directory (use INVOCATION_ID
to build TMP_DIR) and update all subsequent reads/merges to use "$TMP_DIR/..."
instead of /tmp/..., ensure the directory is created before use and removed
after use (rm -rf "$TMP_DIR") to clean up; update the curl invocations and wait
block to reference the new TMP_DIR variable so concurrent skill invocations do
not overwrite each other.
- Around line 71-78: The Python one-liner that sets COMMUNITY_UID interpolates
${NAME} directly into the inline script (see COMMUNITY_UID assignment and the
python snippet), which allows command injection; change the approach to pass the
ecosystem name as a safe command-line argument to Python (use sys.argv inside
the script rather than embedding ${NAME} into the source), read the JSON and
compare against sys.argv[1] (or argv[n]) to locate the matching community UID,
and invoke Python with the NAME as a separate argument instead of embedding it
in the quoted script.

---

Nitpick comments:
In `@skills/find-funding-opportunities/SKILL.md`:
- Line 118: Update the inline code in the Ecosystem line to avoid spaces inside
code spans: replace the backticked "`, ` " with either a description like
"comma-separated" or a backticked comma without the trailing space (e.g., change
the fragment in the line that reads "**Ecosystem**: `metadata.ecosystems` joined
with `, ` (fall back to `communities[0].name`)” so the separator is written as
"comma-separated" or `` `,` ``), ensuring no spaces inside the code span.

In `@skills/funding-digest/SKILL.md`:
- Around line 75-88: Update the fenced code blocks in SKILL.md to include
language specifiers: add ```markdown for the output-format templates that start
with the header "Funding Digest — Week of {Mon DD}" (both the filled and "No new
programs" variants referenced around lines 75-100) and use ```text for the cron
schedule block that contains "Schedule: 0 9 * * 1" (the example at ~114-117);
ensure every triple-backtick fence in those examples is annotated accordingly so
static analyzers recognize the block language.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 96c41f67-b498-4313-b274-e511b84e4426

📥 Commits

Reviewing files that changed from the base of the PR and between 4582eea and 635ad5a.

📒 Files selected for processing (9)
  • .claude-plugin/marketplace.json
  • .claude/skills/skill-creator/SKILL.md
  • README.md
  • skills/find-funding-opportunities/SKILL.md
  • skills/find-funding-opportunities/references/api-reference.md
  • skills/funding-digest/SKILL.md
  • skills/project-manager/SKILL.md
  • skills/setup-agent/SKILL.md
  • skills/skill-creator/SKILL.md

Comment on lines +65 to +68
curl -s "${H[@]}" "https://gapapi.karmahq.xyz/v2/communities?limit=100" > /tmp/kf_communities.json &
curl -s "${H[@]}" "${BASE}${EXTRA}&ecosystems=${NAME}" > /tmp/kf_eco.json &
curl -s "${H[@]}" "${BASE}${EXTRA}&name=${NAME}" > /tmp/kf_name.json &
wait

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

MAJOR: Race condition with fixed temporary filenames.

The temporary files use fixed names (/tmp/kf_communities.json, etc.) without incorporating $INVOCATION_ID. If multiple skill invocations run simultaneously, they will overwrite each other's temporary files, causing incorrect merged results.

♻️ Proposed fix incorporating INVOCATION_ID
 # Run community lookup + ecosystems + name queries in parallel
-curl -s "${H[@]}" "https://gapapi.karmahq.xyz/v2/communities?limit=100" > /tmp/kf_communities.json &
-curl -s "${H[@]}" "${BASE}${EXTRA}&ecosystems=${NAME}" > /tmp/kf_eco.json &
-curl -s "${H[@]}" "${BASE}${EXTRA}&name=${NAME}" > /tmp/kf_name.json &
+TMP_DIR="/tmp/kf_${INVOCATION_ID}"
+mkdir -p "$TMP_DIR"
+curl -s "${H[@]}" "https://gapapi.karmahq.xyz/v2/communities?limit=100" > "$TMP_DIR/communities.json" &
+curl -s "${H[@]}" "${BASE}${EXTRA}&ecosystems=${NAME}" > "$TMP_DIR/eco.json" &
+curl -s "${H[@]}" "${BASE}${EXTRA}&name=${NAME}" > "$TMP_DIR/name.json" &
 wait

Update all subsequent references to use $TMP_DIR/ prefix, and add cleanup:

rm -rf "$TMP_DIR"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/find-funding-opportunities/SKILL.md` around lines 65 - 68, The curl
commands write to fixed temp files (/tmp/kf_communities.json, /tmp/kf_eco.json,
/tmp/kf_name.json) causing race conditions; change them to write into a unique
temp directory (use INVOCATION_ID to build TMP_DIR) and update all subsequent
reads/merges to use "$TMP_DIR/..." instead of /tmp/..., ensure the directory is
created before use and removed after use (rm -rf "$TMP_DIR") to clean up; update
the curl invocations and wait block to reference the new TMP_DIR variable so
concurrent skill invocations do not overwrite each other.

Comment on lines +71 to +78
COMMUNITY_UID=$(python3 -c "
import json
data = json.load(open('/tmp/kf_communities.json'))
name = '${NAME}'.lower()
for c in data.get('payload', []):
if name in c.get('details', {}).get('name', '').lower():
print(c['uid']); break
" 2>/dev/null)

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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify if there are other shell scripts in the repository that might have similar injection risks
rg -n -t md -C 2 'python3 -c.*\$\{[A-Z_]+\}'

Repository: show-karma/skills

Length of output: 43


🏁 Script executed:

#!/bin/bash
# First, let's find and read the specific file mentioned in the review
find . -name "SKILL.md" -path "*/find-funding-opportunities/*" | head -5

Repository: show-karma/skills

Length of output: 105


🏁 Script executed:

#!/bin/bash
# Get more context around the vulnerability
if [ -f "skills/find-funding-opportunities/SKILL.md" ]; then
  sed -n '60,90p' "skills/find-funding-opportunities/SKILL.md" | cat -n
fi

Repository: show-karma/skills

Length of output: 1460


🏁 Script executed:

#!/bin/bash
# Search more broadly for python3 -c patterns with variable interpolation in all files
rg 'python3.*-c.*\$\{' -A 3 -B 1 --max-count=20

Repository: show-karma/skills

Length of output: 43


CRITICAL: Command injection vulnerability in Python snippet.

Line 15 interpolates ${NAME} directly into a Python string without escaping. If the ecosystem name contains a single quote, it breaks out of the string literal and executes arbitrary Python code.

Example attack: NAME="'; import os; os.system('malicious'); #"

Since this documentation guides AI agents constructing these commands from user input, proper escaping is essential. Use sys.argv to pass the variable safely:

Recommended fix
 COMMUNITY_UID=$(python3 -c "
 import json
+import sys
 data = json.load(open('/tmp/kf_communities.json'))
-name = '${NAME}'.lower()
+name = sys.argv[1].lower()
 for c in data.get('payload', []):
     if name in c.get('details', {}).get('name', '').lower():
         print(c['uid']); break
-" 2>/dev/null)
+" "$NAME" 2>/dev/null)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
COMMUNITY_UID=$(python3 -c "
import json
data = json.load(open('/tmp/kf_communities.json'))
name = '${NAME}'.lower()
for c in data.get('payload', []):
if name in c.get('details', {}).get('name', '').lower():
print(c['uid']); break
" 2>/dev/null)
COMMUNITY_UID=$(python3 -c "
import json
import sys
data = json.load(open('/tmp/kf_communities.json'))
name = sys.argv[1].lower()
for c in data.get('payload', []):
if name in c.get('details', {}).get('name', '').lower():
print(c['uid']); break
" "$NAME" 2>/dev/null)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/find-funding-opportunities/SKILL.md` around lines 71 - 78, The Python
one-liner that sets COMMUNITY_UID interpolates ${NAME} directly into the inline
script (see COMMUNITY_UID assignment and the python snippet), which allows
command injection; change the approach to pass the ecosystem name as a safe
command-line argument to Python (use sys.argv inside the script rather than
embedding ${NAME} into the source), read the JSON and compare against
sys.argv[1] (or argv[n]) to locate the matching community UID, and invoke Python
with the NAME as a separate argument instead of embedding it in the quoted
script.

Comment on lines 104 to 113
```
Found 42 programs (showing top 10):

1. **Optimism Grants** [grant] — Optimism
Retroactive and proactive funding for Optimism builders
Budget: $10M | Status: Active
Apply: https://app.charmverse.io/...

2. **ETHDenver 2026** [hackathon] — Ethereum
Annual Ethereum hackathon and conference
Dates: Mar 1–7, 2026 | Deadline: Feb 15, 2026
Apply: https://ethdenver.com/apply
Found {count} programs (showing top 10):

3. **Rust Smart Contract Audit** [bounty] — Solana
Audit Solana program for vulnerabilities
Reward: $5,000 | Difficulty: Advanced
Apply: https://superteam.fun/...
1. **{title}** [{type}] — {ecosystems}
{description, ~120 chars}
{detail line} | Deadline: {deadline or "Rolling"}
Apply: {submissionUrl}

Showing 10 of 42. Ask for more or narrow your search.
Showing 10 of {count}. Ask for more or narrow your search.
```

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

Add language specifier to fenced code block.

The code block at line 104 is missing a language identifier, which can affect rendering and accessibility. Since this is an output template, consider adding text or markdown after the opening fence.

📝 Proposed fix
-```
+```text
 Found {count} programs (showing top 10):

As per static analysis hints: "Fenced code blocks should have a language specified (MD040)."

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 104-104: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/find-funding-opportunities/SKILL.md` around lines 104 - 113, The
fenced code block containing the output template starting with "Found {count}
programs (showing top 10):" in SKILL.md is missing a language specifier; update
the opening fence to include a language (e.g., change ``` to ```text or
```markdown) so the block becomes labeled (this addresses MD040 and improves
rendering/accessibility for the template output shown in the Find Funding
Opportunities skill).

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