/last30days <topic> is not a prompt and not a normal program. It is both: a 2,307-line instruction contract (SKILL.md) that scripts what the host LLM must do, plus a large deterministic Python engine (scripts/last30days.py + ~90 library modules) that the LLM runs via shell. The LLM resolves entities and writes a JSON query plan; the engine fans out to ~20 platforms in parallel, merges everything with weighted Reciprocal Rank Fusion, filters to the last 30 days, groups items into story clusters scored by upvotes, likes, views and prediction-market money; then the LLM reads the ranked evidence and writes the final brief under eight strict formatting "LAWs". The free tier needs zero API keys (Reddit, HN, Polymarket, GitHub); a setup wizard unlocks X, YouTube, TikTok and others using your own browser cookies and keys.
1. What it is
last30days is an Agent Skill: a folder containing a SKILL.md file (metadata plus instructions the agent follows) and a scripts/ directory with executable code. The format is an open standard originally developed by Anthropic and supported by 50+ agent runtimes ("harnesses"): Claude Code, OpenAI Codex, Cursor, Copilot, Gemini CLI, OpenClaw and others. Installation is either the Claude Code plugin marketplace (/plugin install last30days) or Vercel's skills CLI (npx skills add mvanhorn/last30days-skill -g), which symlinks the skill into whichever agents it detects on your machine.
The pitch, in the project's own words: "An AI agent-led search engine scored by upvotes, likes, and real money - not editors." Google indexes editorial pages; ChatGPT can search Reddit but not X; Gemini has YouTube but not Reddit. Each platform is a walled garden. last30days bridges them by letting an agent bring your own credentials and browser sessions to every platform at once, then ranking what it finds by what real people engaged with in the last 30 days.
Typical uses documented in the README: pre-meeting research on a person (recent PRs, X posts, podcast transcripts), tool comparisons with live GitHub star counts, breaking-news synthesis with Polymarket odds, trip planning from community threads, and --hiring-signals reports built from a company's live job pages.
2. The core design: a prose contract driving a Python engine
The repository's own CONCEPTS.md draws the line precisely:
- The Skill (SKILL.md) is the agent-facing surface: 2,307 lines of instructions telling the host LLM exactly which pre-research to do, which flags to pass, and what shape of output is legal.
- The Engine (scripts/last30days.py) is the implementation: a Python CLI that does all retrieval, filtering, scoring, clustering and rendering deterministically. It has no hard dependency on any LLM.
- The Harness is whatever agent runtime loaded the skill. The same engine runs everywhere; SKILL.md branches on harness capabilities (for example: does this session have a WebSearch tool?).
The division of labor is the interesting part. Work that needs judgment (disambiguating "Kevin Rose", deciding what subqueries to search, writing the final narrative) is assigned to the host LLM. Work that needs reliability (hitting 20 APIs in parallel, date filtering, deduplication, engagement math) is assigned to Python. The contract between them is explicit: the LLM passes a JSON plan file in, the engine emits ranked evidence and a mandatory footer out, and the LLM is required to pass certain engine blocks through verbatim.
3. Anatomy of a run, step by step
When you type /last30days Peter Steinberger in a harness, SKILL.md walks the model through a fixed sequence:
- Stale-clone self-check (Step 0). The model verifies it did not load SKILL.md from Claude Code's auto-restored
marketplaces/git clone, which can lag the versioned plugin cache by a release. If it did, it re-reads the cached copy. - First-run gate. A one-line grep for
SETUP_COMPLETE=truein~/.config/last30days/.env. On first run the model must run the setup wizard before any research: it installsyt-dlp(YouTube), the free Digg/arXiv/Techmeme CLIs, and extracts X cookies from your browser. - Query-quality pre-flight (Step 0.45). Keyword-trap topics ("gift for 42 year old man", bare "sneakers") get reframed or trigger one clarifying question, because nobody titles a Reddit post that way and the engine would return noise.
- Entity resolution (Steps 0.5-0.55). Using the host's WebSearch tool, the model resolves the topic's X handle, GitHub username or repos, relevant subreddits, TikTok hashtags and Instagram creators. Person topics must produce at least
--x-handle,--github-userand--subreddits. Collision-prone names get an anchor ("kevin rose digg founder", not "kevin rose"). - Query plan (Step 0.75). The model writes a JSON plan: an intent label (breaking_news, comparison, how_to, prediction...), a freshness mode, a cluster mode, and 1-4 weighted subqueries, each with a keyword-style
search_query, a natural-languageranking_query, and a source list. The plan goes into a tmpfile passed as--plan; SKILL.md is emphatic that "YOU are the planner" so the engine's internal LLM planner is bypassed whenever a reasoning model is hosting. - Engine run (Step 1). One foreground Bash call:
python3 $SKILL_DIR/scripts/last30days.py "topic" --plan $FILE --x-handle=... --subreddits=... --emit=compact. The engine does everything in Section 4 below and prints ranked evidence bounded by<!-- EVIDENCE FOR SYNTHESIS -->markers, plus a footer bounded by<!-- PASS-THROUGH FOOTER -->markers. - Web supplements (Step 2). The model runs exactly 2-3 host WebSearches for the long-form context social platforms lack (critic reviews, news explainers), then appends a
## WebSearch Supplemental Resultssection to the saved raw file so the research library records every source that informed the brief (Step 2.5). - Synthesis. The model reads the evidence clusters and writes the brief: a version badge line,
What I learned:, bold-lead-in narrative paragraphs with quotes and numbers, aKEY PATTERNS from the research:numbered list, the engine footer verbatim, and a closing invitation. The evidence clusters themselves are input, never output.
4. Inside the engine
4.1 Sources
| Source | How it is fetched | Cost |
|---|---|---|
| Keyless RSS + "shreddit" HTML scraping + arctic-shift for dedicated subreddits; per-thread JSON enrichment for real upvotes, ratios, and top comments. ScrapeCreators or an OpenAI web_search path as alternatives. | Free | |
| Hacker News | Public API; front/best listings in discovery mode. | Free |
| Polymarket | Public API; real-money odds and volume, auto-included for prediction intents. | Free |
| GitHub | Public API. Person mode: PR velocity, merge rate, top repos. Project mode: issues, discussions, releases, live star counts. | Free |
| arXiv / Techmeme / Digg | Free companion CLIs (arxiv-pp-cli, techmeme-pp-cli, digg-pp-cli) generated by the author's Printing Press project; auto-enabled when on PATH. | Free |
| X / Twitter | Bundled "Bird" GraphQL client driven by your browser cookies (AUTH_TOKEN + CT0), with FROM and ABOUT search lanes; falls back to the paid xAI API (grok + x_search tool). | Free with cookies |
| YouTube | yt-dlp search plus full transcript extraction; comments included; ScrapeCreators transcript backup. | Free |
| TikTok / Instagram / LinkedIn / Threads / Pinterest | ScrapeCreators API, including spoken-word transcripts for Reels and rank-diversified comments. | API key |
| Bluesky / Truth Social / StockTwits / Xiaohongshu | AT Protocol app password, token, public API, or a local MCP bridge respectively; StockTwits auto-activates for tickers. | Mostly free |
| Web / Perplexity / Amazon reviews / Trustpilot | Brave, Exa, Serper or Parallel search keys, Perplexity API modes including Deep Research, Bright Data for Amazon buyer signals. | API keys |
All sources run concurrently under a ThreadPoolExecutor with per-source timeouts and a wall-clock budget; a paid-source budget object caps how many billable fetches a run may consume.
4.2 Ranking: engagement-weighted rank fusion
Each subquery in the plan queries each of its sources, producing many independently ranked "streams". The fusion stage (lib/fusion.py) merges them with weighted Reciprocal Rank Fusion: every item at rank r in a stream contributes subquery_weight × source_weight / (K + r) to the candidate keyed by its normalized URL, so items found by multiple subqueries or platforms accumulate score. Copies of the same item are merged keeping the richest version (for example the copy whose comments were fetched).
Three safeguards keep engagement from becoming a spam vector:
- Entity grounding. A candidate must plausibly mention the primary entity (keyed on its head token). Failing candidates take a decisive demotion that no amount of upvotes can outweigh; the check is deliberately conservative so its own failure modes degrade toward "no penalty" rather than burying real signal.
- Relevance floor with engagement keepers. A viral off-topic thread cannot hijack a brief, but the month's genuinely most-discussed on-topic threads survive stream truncation via reserved "keeper" slots (2/3/4 by depth) even when their title barely overlaps the query.
- Diversity caps. Per-author caps and comment-diversity rules stop one loud account or one hot thread from supplying every quote.
Candidates are then clustered into stories by entity overlap (lib/cluster.py), each cluster carrying a score, item count, source list, and honesty labels such as Uncertainty: single-source or thin-evidence. If every cluster fails the floor, the engine reports "Nothing solid this window" instead of padding, and the synthesis rules require relaying that honestly.
4.3 Output and persistence
With --emit=compact the engine prints the version badge, evidence clusters, stats, partial-coverage report (which sources timed out, rate-limited, or legitimately found nothing), and the emoji-tree footer beginning ✅ All agents reported back! with per-source counts. Every run is also saved as a slugified Markdown file (optionally JSON or a styled HTML page) under ~/Documents/Last30Days/, building a personal research library with offline SQLite full-text search (library search), a browsable HTML feed with Atom export (library feed), and a topic queue that tracks what discovery has surfaced and what you have marked "covered".
5. The output contract: a badge and eight LAWs
The most unusual part of the project is how aggressively SKILL.md constrains the LLM's final answer. The synthesis must open with a badge line (🌐 last30days v3.23.0 · synced 2026-09-02) and obey numbered LAWs, each annotated with the dated, named production failure it prevents:
| LAW | Rule | Failure it fixed |
|---|---|---|
| 1 | No trailing Sources: block; the engine footer is the only visible citation. | WebSearch's own tool contract kept coercing models into appending source lists. |
| 2 | No invented title; body starts What I learned: (comparison queries get one fixed title format). | Runs that invented headlines like "Kanye West: the last 30 days". |
| 3 | No em-dashes or en-dashes, ever ("the most reliable AI-slop tell"). | Generic LLM prose style. |
| 4 | No ## section headers in the body except the fixed comparison template. | Blog-post-shaped output with improvised sections. |
| 5 | Engine footer passed through verbatim, never recomputed. | Models paraphrasing or dropping the stats tree. |
| 6 | Raw evidence clusters are input, never output; transform them into prose. | Two runs that dumped the ranked cluster block at the user. |
| 7 | The host model is the planner; --plan is mandatory on named-entity topics. | Bare engine runs with keyword-only search and thin results. |
| 8+ | Further rules govern honest partial-coverage language ("never write 'nothing on X' when X timed out") and the discovery relay. | Overclaiming quiet sources. |
This is prompt engineering run like a post-incident process: the file documents a "0/8 regression" day (eight consecutive public runs where the model improvised), names each disaster, and encodes the fix as a structural anchor. It even includes a worked example showing an evidence block and the exact prose a model should produce from it.
6. Beyond a single topic: the other modes
Discovery ("what's exploding in AI agents?")
Topic-less trending mode runs a three-leg, host-judged protocol with persisted checkpoints between legs:
- Nominate.
--discover --nominate-onlysweeps river listings (Reddit category feeds, HN front/best, Digg's AI 1000, X when authenticated), clusters items into candidate topics, and writes a nominations bundle. - Judge (the LLM). The model reads the bundle and writes a judgments file: a short searchable name, a junk flag (help-me posts and promo cannot carry a story), and a 0-100 content-worthiness score per nomination.
- Research.
--discover --judgments FILEruns a full research pipeline pass on every surviving topic in parallel against a wall-clock budget. - Angles + finalize. The model writes podcast and X-article hooks per topic;
--finalize --angles FILErenders 5-10 velocity-ranked trend cards, each with cross-source numbers, a momentum label, and a ready-to-run follow-up command.
Every topic must clear an absolute confidence floor (cross-source corroboration or a genuinely strong single-source spike); a run where nothing qualifies renders an honest "Nothing solid this window" with the nearest weak signal named. Surfaced topics persist in the topic queue so repeats get annotated and covered stories stay covered.
Comparison, hiring signals, watchlist, doctor
- Comparison ("X vs Y vs Z"): per-entity engine passes plus a head-to-head pass, rendered into a fixed template with a Quick Verdict, per-entity sections, and a head-to-head table with live GitHub stats.
--hiring-signals: a company's current job and careers pages become cited evidence about focus shifts.- Watchlist: scheduled re-runs of saved topics with delta reports between runs, suitable for cron delivery.
- Doctor:
doctorprobes every source's configuration up front and prescribes exact fixes (missing key, CLI off PATH, expired cookie);doctor --postmortemreads the last run's per-source status to explain what actually broke;--diagnosegenuinely probes auth rather than guessing. - Registers:
--register=exec|dev|creator|eli5re-voices the brief for an audience;--as-ofgives historical lookback windows;--days=N,--quick,--deeptune breadth.
7. Setup, credentials, and the free tier
Zero-config: Reddit, HN, Polymarket and GitHub work with no keys at all (the "keyless path", where local lexical scoring replaces LLM reranking). The first-run wizard then unlocks more in about 30 seconds: it installs yt-dlp and the free source CLIs and extracts X session cookies from Chrome, Safari, Brave, Edge, Vivaldi, Opera or Arc. Credentials resolve through three tiers: .env files (~/.config/last30days/.env or project-scoped), macOS Keychain items prefixed last30days-, and Linux pass(1). Optional keys (ScrapeCreators, xAI, OpenAI, OpenRouter, Perplexity, Brave, Apify, Bluesky app passwords, and more) each unlock specific sources; a missing key just means that source is skipped and reported as unconfigured. On hosts without Python 3.12 the preflight provisions a uv-managed interpreter automatically.
8. Adoption and project health
- Created February 2026; first hit GitHub Trending #1 on March 25, 2026; #1 Python repository of the day and week, #6 repository of the month for June 2026 (Trendshift).
- 61.1k stars, 5.3k forks, 1,203 commits, 49 tagged releases, 76 branches as of September 2, 2026; active daily maintenance.
- 37.3K installs via the skills.sh registry at roughly 2,000 per week, in addition to Claude Code marketplace installs.
- Heavily community-driven: 122 of 175 PRs in one three-month stretch came from 52 outside contributors; CI includes OpenSSF Scorecard, Semgrep, OSV-Scanner, zizmor, dependency review, and an 84% test-coverage floor across 200+ end-to-end test files.
- Author Matt Van Horn co-founded June (the "self-driving oven", acquired by Weber) and the company that became Lyft. Sibling projects supply parts: Printing Press generates the free
*-pp-clisource tools, and agentcookie syncs browser sessions to remote agent machines.
9. Security and trust model
Read before installing. The capabilities that make last30days work are exactly the ones security scanners flag. Gen Agent Trust Hub rates the skill HIGH risk (verdict: Fail, May 2026), Snyk fails it, and Socket warns, citing four findings:
- Credential access:
chrome_cookies.py,safari_cookies.pyandcookie_extract.pyprogrammatically extract and decrypt browser cookie databases;env.pyandsetup-keychain.shread API keys from the macOS Keychain. - Data egress: those tokens authenticate requests to third-party APIs (ScrapeCreators, xAI, OpenRouter), so your session cookies and keys transit services you must trust.
- Instruction override: SKILL.md's "VOICE CONTRACT LAW" deliberately overrides the host agent's global preferences and the WebSearch tool's own citation mandate; structurally this is the same mechanism a prompt-injection attack would use, here used openly by the skill's author.
- Shell execution: many scripts run subprocesses for system tasks.
None of this is hidden; it is the documented bring-your-own-credentials design, the repo ships a Security & Permissions section, and the team has an active hardening record (stored-XSS fixes, locked-down cookie temp files, an RCE fix in a session hook, build provenance attestation). But installing it means letting an agent read your browser sessions and keychain and act on them. Review the source, scope the keys you provide, and skip cookie extraction if X search is not worth it to you.
10. Sources
- Repository and docs: github.com/mvanhorn/last30days-skill (README.md, SKILL.md v3.23.0, CONCEPTS.md, CONFIGURATION.md, docs/how-search-works.md, engine source under skills/last30days/scripts/), inspected from a local clone on 2026-09-02.
- Agent Skills format: agentskills.io; Claude Code skills documentation: code.claude.com/docs/en/skills.
- Trend history: trendshift.io/repositories/21997; HN submissions via hn.algolia.com.
- Author: github.com/mvanhorn.
- Distribution: npmjs.com/package/skills; registry stats and security audits: skills.sh listing and its Gen Agent Trust Hub audit; architecture cross-check: deepwiki.com/mvanhorn/last30days-skill.
Report generated 2026-09-02 by KISS Sorcar from the repository at v3.23.0 and ten independently visited web sources.