last30days-skill
CLI Toolmvanhorn/last30days-skill
AI agent skill researching topics across social media and web with grounded summaries.
Overview
An AI agent-driven search engine that aggregates content from Reddit, X, YouTube, TikTok, and more. Scores results by real engagement and synthesizes a grounded summary. Bridges walled-garden platforms to reveal what people actually care about.
README Preview
# /last30days\n\n\n \n \n \n \n \n \n \n\n\n**An AI agent-led search engine scored by upvotes, likes, and real money - not editors.**\n\nThis README tracks the current v3 pipeline. The runtime skill spec lives in [skills/last30days/SKILL.md](skills/last30days/SKILL.md), which is the source of truth for the latest command and setup behavior.\n\n**Claude Code (recommended — auto-updates via marketplace):**\n```\n/plugin marketplace add mvanhorn/last30days-skill\n/plugin install last30days\n```\n\n**Codex, Cursor, Copilot, Gemini CLI, or any of 50+ [Agent Skills](https://agentskills.io) hosts:**\n```\nnpx skills add mvanhorn/last30days-skill -g\n```\n(`-g` installs globally for your user, available across all projects. Drop it to scope per-project.)\n\nMore install options (claude.ai web, OpenClaw, manual) in the [Install](#install) section below.\n\nZero config. Reddit, HN, Polymarket, and GitHub work immediately. Run it once and the setup wizard unlocks X, YouTube, TikTok, and more in 30 seconds.\n\n---\n\nReddit upvotes. X likes. YouTube transcripts. TikTok engagement. Polymarket odds backed by real money and insider information. That's millions of people voting with their attention and their wallets every day. /last30days searches all of it in parallel, scores it by what real people actually engage with, and an AI agent judge synthesizes it into one brief.\n\nGoogle aggregates editors. /last30days searches people.\n\nYou can't get this search anywhere else because no single AI has access to all of it. Google search doesn't touch Reddit comments or X posts. ChatGPT has a deal with Reddit but can't search X or TikTok. Gemini has YouTube but not Reddit. Claude has none of them natively. Each platform is a walled garden with its own API, its own tokens, its own auth. But you can bring your own keys and browser sessions, and suddenly an AI agent can search all of them at once, score them against each other, and tell you what actually matters.\n\nThat's the un
FAQ (5)
TroubleshootingHow to disable the ScrapeCreators fallback for YouTube only without removing the SCRAPECREATORS_API_KEY?
Set the environment variable LAST30DAYS_YOUTUBE_BACKEND=yt-dlp (added in #1319). This forces YouTube to use yt-dlp only—no ScrapeCreators credits are spent on transcript fallback, search backfill, or comments—while SCRAPECREATORS_API_KEY stays active for other sources like X and Reddit. The update also improves yt-dlp itself: it now pulls uploaded subtitles and original-language captions on its own, and paid calls stop once a run ends. Note that previously, merely having the key set put yt-dlp into fast-fail mode (a single 12s attempt instead of 3 retries with backoff and a 30s timeout), so transient 429 errors jumped straight to paid SC calls; the backend flag also restores the full keyless retry budget. Workarounds that do NOT fully work: LAST30DAYS_YT_SC_MIN_ITEMS=0 only disables the thin-search backfill, and removing the key disables ScrapeCreators for every source.
TroubleshootingWhy does Instagram reels search return 404 "No scrapeable reels found" for every query and how to fix it?
The /v2/instagram/reels/search endpoint is dead at the provider level — it returns HTTP 404 for all queries (though no credits are charged). Fix with a two-part patch: (1) In _user_reels(), unwrap the media envelope: it.get("media", it) — otherwise _parse_items() finds no pk/caption/play_count fields and silently drops all reels. (2) In search_instagram(), when v2 search returns empty or raises HTTPError, fall back to a profile-based lane instead of returning early: call GET /v1/instagram/search/profiles?query=<keyword> (1 credit), filter accounts below a follower floor and sort by follower count (profile matching is loose), then fetch GET /v1/instagram/user/reels?handle=<handle> for the top N accounts and truncate to results_per_page. Comments can be pulled via GET /v2/instagram/post/comments?url=<reel_url>. Total cost: ~4-5 credits per keyword. Only surface the original 404 error if the fallback also returns nothing.
TroubleshootingHow to fix yt-dlp 'HTTP Error 429: Too Many Requests' when downloading YouTube auto-captions for auto-dubbed videos?
On auto-dubbed YouTube videos, the standard en auto-caption track always returns HTTP 429, while the original-language track en-orig downloads fine. Fix by requesting -orig tracks first, since yt-dlp downloads subtitle languages in order and stops at the first error:
yt-dlp --write-auto-subs --sub-lang en-orig,en --sub-format vtt --skip-download "https://www.youtube.com/watch?v=VIDEO_ID"
In the last30days skill, set the subtitle language list so each language's -orig variant comes before it:
LAST30DAYS_YT_SUB_LANGS=en-orig,en,es-orig,es,pt-orig,pt
This prevents needless fallback to the paid ScrapeCreators backend (which can burn credits and hit HTTP 402). The issue was permanently fixed in last30days via PR #1319, so upgrading to the latest version also resolves it; LAST30DAYS_YOUTUBE_BACKEND=yt-dlp keeps YouTube transcript fetching free.
TroubleshootingHow do I fix the ScrapeCreators transcript fallback returning Arabic or another wrong-language transcript for English YouTube videos?
The fallback calls /v1/youtube/video/transcript without a language parameter, so YouTube may return an auto-dubbed caption track such as Arabic. Explicitly request the preferred language:
curl "https://api.scrapecreators.com/v1/youtube/video/transcript?url=https://www.youtube.com/watch?v=n5bZHETCiJA&language=en"
In the integration, change the request params to:
params={"url": video_url, "language": "en"}
The fixed implementation requests the first three distinct languages from LAST30DAYS_YT_SUB_LANGS (default en,es,pt) and uses the first nonempty transcript. Configure it with, for example:
export LAST30DAYS_YT_SUB_LANGS=en,es,pt
Upgrade to the release containing PR fix(youtube): request the preferred language from the ScrapeCreators transcript fallback. As an additional safeguard, compare the returned track's language with the requested language and treat a mismatch as a failed fallback rather than accepting the foreign-language transcript.
TroubleshootingHow do I fix "can't open file skills/last30days/scripts/last30days.py" after installing the skill globally with npx?
This is a v3.14.0 path regression: setup and HTML-export commands use repository-relative paths or the removed ${SKILL_ROOT} variable instead of ${SKILL_DIR}.
Immediate workaround from any workspace:
export SKILL_DIR="$HOME/.agents/skills/last30days"
"${LAST30DAYS_PYTHON:-python3}" "${SKILL_DIR}/scripts/last30days.py" --welcome
Or call the installed script directly:
python3 "$HOME/.agents/skills/last30days/scripts/last30days.py" setup
For a repository checkout, set SKILL_DIR to the absolute skills/last30days directory. In SKILL.md, replace every skills/last30days/scripts/last30days.py invocation with "${SKILL_DIR}/scripts/last30days.py". In references/save-html-brief.md, replace "${SKILL_ROOT}/scripts/last30days.py" with "${SKILL_DIR}/scripts/last30days.py". PR #1231 implements this fix.