- Xiaohongshu search via local MCP service (opt-in, zero impact if service not running) - Reddit public JSON fallback (works with zero API keys) - Reddit priority: ScrapeCreators -> OpenAI -> public fallback - Updated env.py: Reddit always available via public fallback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.6 KiB
title, type, date
| title | type | date |
|---|---|---|
| ClawHub Scanner Compliance for last30days-official | feat | 2026-02-15 |
ClawHub Scanner Compliance for last30days-official
Overview
Make the last30days skill pass ClawHub's security scanner (VirusTotal + Code Insight) so it can be published as last30days-official. The user's 8 other mvanhorn skills already pass - we replicate their exact pattern.
Problem Statement
ClawHub requires skills to pass a multi-layer security scan before publication:
- Metadata validation (frontmatter fields)
- VirusTotal automated scanning
- LLM-powered Code Insight analysis (checks if capabilities match documentation)
- Credential handling review
The current last30days SKILL.md has basic metadata.clawdbot but is missing fields the scanner checks: emoji, user-invocable, disable-model-invocation, files declaration. There's no ## Security & Permissions section (required pattern from passing skills). README has no security/privacy documentation.
Proposed Solution
Follow the exact pattern from clawdbot-skill-xai and clawdbot-skill-search-x (both pass the scanner). Three files need changes.
Fix 1: SKILL.md Frontmatter
Add missing scanner fields to the existing frontmatter:
---
name: last30days
version: "2.1"
description: "Research a topic from the last 30 days. Also triggered by 'last30'. Sources: Reddit, X, YouTube, web."
argument-hint: 'last30 AI video tools, last30 best project management tools'
allowed-tools: Bash, Read, Write, AskUserQuestion, WebSearch
homepage: https://github.com/mvanhorn/last30days-skill
user-invocable: true
disable-model-invocation: true
metadata:
clawdbot:
emoji: "📰"
requires:
env:
- OPENAI_API_KEY
bins:
- node
- python3
primaryEnv: OPENAI_API_KEY
files:
- "scripts/*"
homepage: https://github.com/mvanhorn/last30days-skill
tags:
- research
- reddit
- x
- youtube
- trends
- prompts
---
Key additions:
user-invocable: true- human must trigger itdisable-model-invocation: true- agent cannot self-triggeremoji: "📰"- required display fieldfiles: ["scripts/*"]- prevents false "instruction-only but has scripts" flag
Fix 2: Security & Permissions Section in SKILL.md
Add to the bottom of SKILL.md (matches xai/search-x pattern exactly):
## Security & Permissions
**What this skill does:**
- Sends search queries to OpenAI's Responses API (`api.openai.com`) for Reddit discovery
- Sends search queries to Twitter's GraphQL API (via browser cookie auth) or xAI's API (`api.x.ai`) for X search
- Runs `yt-dlp` locally for YouTube search and transcript extraction (no API key, public data)
- Optionally sends search queries to Brave Search API, Parallel AI API, or OpenRouter API for web search
- Fetches public Reddit thread data from `reddit.com` for engagement metrics
- Stores research findings in local SQLite database (watchlist mode only)
**What this skill does NOT do:**
- Does not post, like, or modify content on any platform
- Does not access your Reddit, X, or YouTube accounts
- Does not share API keys between providers (OpenAI key only goes to api.openai.com, etc.)
- Does not log, cache, or write API keys to output files
- Does not send data to any endpoint not listed above
- Cannot be invoked autonomously by the agent (`disable-model-invocation: true`)
**Bundled scripts:** `scripts/last30days.py` (main research engine), `scripts/lib/` (search, enrichment, rendering modules), `scripts/lib/vendor/bird-search/` (vendored X search client, MIT licensed)
Review scripts before first use to verify behavior.
Fix 3: Security & Privacy Section in README.md
Add after the "How It Works" section:
## Security & Privacy
### Data that leaves your machine
| Destination | Data Sent | API Key Required |
|------------|-----------|-----------------|
| `api.openai.com` | Search query (topic string) | OPENAI_API_KEY |
| `reddit.com` | Thread URLs for enrichment | None (public JSON) |
| Twitter GraphQL / `api.x.ai` | Search query | Browser cookies or XAI_API_KEY |
| `youtube.com` (via yt-dlp) | Search query | None (public search) |
| `api.search.brave.com` | Search query (optional) | BRAVE_API_KEY |
| `api.parallel.ai` | Search query (optional) | PARALLEL_API_KEY |
| `openrouter.ai` | Search query (optional) | OPENROUTER_API_KEY |
Your research topic is included in all outbound API requests. If you research sensitive topics, be aware that query strings are transmitted to the API providers listed above.
### Data stored locally
- API keys: `~/.config/last30days/.env` (chmod 600 recommended)
- Watchlist database: `~/.local/share/last30days/research.db` (SQLite)
- Briefings: `~/.local/share/last30days/briefs/`
### API key isolation
Each API key is transmitted only to its respective endpoint. Your OpenAI key is never sent to xAI, Brave, or any other provider. Browser cookies for X are read locally and used only for Twitter GraphQL requests.
Fix 4: Update .claude-plugin Files
plugin.json - bump version, add youtube keyword:
{
"name": "last30days",
"description": "Research any topic from the last 30 days across Reddit, X, YouTube, and the web",
"version": "2.1.0",
"author": {"name": "mvanhorn"},
"repository": "https://github.com/mvanhorn/last30days-skill",
"license": "MIT",
"keywords": ["research", "reddit", "twitter", "x", "youtube", "trends", "prompts"],
"skills": ["./"]
}
marketplace.json - add version, update description:
{
"name": "last30days",
"owner": {"name": "mvanhorn", "url": "https://github.com/mvanhorn"},
"metadata": {
"description": "Research any topic from the last 30 days across Reddit, X, YouTube, and the web",
"version": "2.1.0"
},
"plugins": [{"name": "last30days", "source": "."}]
}
What We DON'T Need
Based on the audit of your 8 passing skills:
- Script-level security manifest headers - your passing skills (xai, search-x, parallel) do NOT have these. The scanner relies on SKILL.md, not per-file headers.
- Separate SECURITY.md file - not needed; README section + SKILL.md section is sufficient.
- Shell injection fixes - already clean. All subprocess calls use list-form args, no
shell=Trueanywhere. - Credential leak fixes - already clean. All keys loaded from env vars, none hardcoded or logged.
Acceptance Criteria
- SKILL.md frontmatter has
user-invocable,disable-model-invocation,emoji,files - SKILL.md has
## Security & Permissionssection with "does" and "does NOT do" lists - README.md has
## Security & Privacysection with endpoint table and key isolation docs - plugin.json version bumped to 2.1.0, youtube keyword added
- marketplace.json version and description updated
python3 scripts/last30days.py --diagnosestill works after changes- Synced to all installed skill locations
- Published to ClawHub as
last30days-official(when auth is fixed)
Files to Modify
| File | Change |
|---|---|
SKILL.md |
Add frontmatter fields + Security & Permissions section |
README.md |
Add Security & Privacy section |
.claude-plugin/plugin.json |
Bump version, add youtube keyword |
.claude-plugin/marketplace.json |
Add version, update description |
References
- 13-point ClawHub checklist
- ClawHub docs
- ClawHub Developer Guide 2026
- Your passing skills:
clawdbot-skill-xai,clawdbot-skill-search-x(exact pattern replicated)