Compare commits
2 Commits
v2.9.1
..
69aa98f3f8
| Author | SHA1 | Date | |
|---|---|---|---|
| 69aa98f3f8 | |||
| 6edb813bea |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "last30days",
|
||||
"description": "Research any topic from the last 30 days across Reddit, X, YouTube, and the web",
|
||||
"version": "2.9.1",
|
||||
"version": "2.1.0",
|
||||
"author": {
|
||||
"name": "mvanhorn"
|
||||
},
|
||||
|
||||
@@ -5,24 +5,6 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.9.1] - 2026-03-05
|
||||
|
||||
### Highlights
|
||||
|
||||
Auto-save research briefings to `~/Documents/Last30Days/` as topic-named .md files. Every run now builds a personal research library automatically - no more manual copy-paste.
|
||||
|
||||
### Added
|
||||
|
||||
- Auto-save complete research briefings (synthesis, stats, follow-up suggestions) to `~/Documents/Last30Days/{topic-slug}.md` after every run
|
||||
- Kebab-case filename generation from topic (e.g., "Claude Code skills" -> `claude-code-skills.md`)
|
||||
- Duplicate topic handling: appends date suffix instead of overwriting (e.g., `claude-code-skills-2026-03-05.md`)
|
||||
- Agent mode (`--agent`) also saves research files
|
||||
- Brief confirmation after save: "Saved to ~/Documents/Last30Days/{slug}.md"
|
||||
|
||||
### Credits
|
||||
|
||||
- [@devin_explores](https://x.com/devin_explores) -- Inspired this feature by sharing their workflow of saving every last30days run into organized .md files ([PR #51](https://github.com/mvanhorn/last30days-skill/pull/51))
|
||||
|
||||
## [2.9.0] - 2026-03-05
|
||||
|
||||
### Highlights
|
||||
@@ -132,7 +114,6 @@ Three headline features: watchlists for always-on bots, YouTube transcripts as a
|
||||
|
||||
Initial public release. Reddit + X search via OpenAI Responses API and xAI API.
|
||||
|
||||
[2.9.1]: https://github.com/mvanhorn/last30days-skill/compare/v2.9.0...v2.9.1
|
||||
[2.9.0]: https://github.com/mvanhorn/last30days-skill/compare/v2.8.0...v2.9.0
|
||||
[2.8.0]: https://github.com/mvanhorn/last30days-skill/compare/v2.6.0...v2.8.0
|
||||
[2.1.0]: https://github.com/mvanhorn/last30days-skill/compare/v1.0.0...v2.1.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: last30days
|
||||
version: "2.9.1"
|
||||
version: "2.9"
|
||||
description: "Research a topic from the last 30 days. Also triggered by 'last30'. Sources: Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, web. Become an expert and write copy-paste-ready prompts."
|
||||
argument-hint: 'last30 AI video tools, last30 best project management tools'
|
||||
allowed-tools: Bash, Read, Write, AskUserQuestion, WebSearch
|
||||
@@ -30,7 +30,7 @@ metadata:
|
||||
- prompts
|
||||
---
|
||||
|
||||
# last30days v2.9.1: Research Any Topic from the Last 30 Days
|
||||
# last30days v2.9: Research Any Topic from the Last 30 Days
|
||||
|
||||
Research ANY topic across Reddit, X, YouTube, TikTok, Hacker News, Polymarket, and the web. Surface what people are actually discussing, recommending, betting on, and debating right now.
|
||||
|
||||
@@ -123,8 +123,6 @@ If `--agent` appears in ARGUMENTS (e.g., `/last30days plaud granola --agent`):
|
||||
5. **Skip** the follow-up invitation ("I'm now an expert on X...")
|
||||
6. **Output** the complete research report and stop - do not wait for further input
|
||||
|
||||
Agent mode still saves the research briefing to `~/Documents/Last30Days/` using the same logic as interactive mode (see "Save Research to Documents" section).
|
||||
|
||||
Agent mode report format:
|
||||
|
||||
```
|
||||
@@ -498,51 +496,6 @@ For `/last30days war in Iran` (NEWS):
|
||||
|
||||
---
|
||||
|
||||
## Save Research to Documents
|
||||
|
||||
After displaying the invitation, save the complete research briefing to the user's Documents folder. This happens automatically on every run.
|
||||
|
||||
1. **Create the directory** (if it doesn't exist):
|
||||
```bash
|
||||
mkdir -p ~/Documents/Last30Days
|
||||
```
|
||||
|
||||
2. **Generate the filename** from TOPIC:
|
||||
- Lowercase the topic
|
||||
- Replace spaces and special characters with hyphens
|
||||
- Remove consecutive hyphens
|
||||
- Trim to 60 characters max
|
||||
- Example: "Claude Code Best Practices" -> `claude-code-best-practices`
|
||||
|
||||
3. **Check for duplicates**: If `~/Documents/Last30Days/{slug}.md` already exists, append today's date: `{slug}-YYYY-MM-DD.md`
|
||||
|
||||
4. **Use the Write tool** to save to `~/Documents/Last30Days/{slug}.md` with this exact structure:
|
||||
|
||||
```markdown
|
||||
# {TOPIC}
|
||||
|
||||
> Researched {date} | Query type: {QUERY_TYPE} | Target tool: {TARGET_TOOL or "general"}
|
||||
|
||||
## What I learned
|
||||
|
||||
{The full synthesis section you just displayed - all topics, patterns, and citations}
|
||||
|
||||
## Stats
|
||||
|
||||
{The full stats box with source counts and engagement - copy exactly as displayed}
|
||||
|
||||
## Follow-up suggestions
|
||||
|
||||
{The 2-3 specific suggestions from the invitation block}
|
||||
|
||||
---
|
||||
*Generated by [last30days](https://github.com/mvanhorn/last30days-skill) v2.9.1*
|
||||
```
|
||||
|
||||
5. **Confirm briefly** after saving: `Saved to ~/Documents/Last30Days/{slug}.md`
|
||||
|
||||
---
|
||||
|
||||
## WAIT FOR USER'S RESPONSE
|
||||
|
||||
After showing the stats summary with your invitation, **STOP and wait** for the user to respond.
|
||||
@@ -654,7 +607,6 @@ Want another prompt? Just tell me what you're creating next.
|
||||
- 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)
|
||||
- Saves research briefings as .md files to ~/Documents/Last30Days/
|
||||
|
||||
**What this skill does NOT do:**
|
||||
- Does not post, like, or modify content on any platform
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
---
|
||||
title: "feat: Auto-save research results to ~/Documents/Last30Days/"
|
||||
type: feat
|
||||
status: completed
|
||||
date: 2026-03-05
|
||||
---
|
||||
|
||||
# feat: Auto-save research results to ~/Documents/Last30Days/
|
||||
|
||||
## Overview
|
||||
|
||||
Every time the last30days skill completes a research run, automatically save the full briefing - inquiry, synthesis, stats, and follow-up suggestions - as a topic-named `.md` file in `~/Documents/Last30Days/`. Inspired by how users like @devin_explores are already manually saving results to build a personal research library (see screenshot - 17 topic files in a `Last30Days` Finder folder, each 9-34 KB).
|
||||
|
||||
## Problem Statement / Motivation
|
||||
|
||||
The skill's most valuable output - the assistant's synthesized "What I learned" briefing with stats and citations - only exists in the conversation. Once the session ends, it's gone. Users like @devin_explores work around this by manually copying output into .md files. Meanwhile, the Python script already writes raw data to `~/.local/share/last30days/out/`, but:
|
||||
|
||||
1. It overwrites on every run (no history)
|
||||
2. It only contains pre-synthesis data (scored items), not the assistant's expert briefing
|
||||
3. It's in a hidden dot-directory users don't naturally browse
|
||||
|
||||
The feature makes saving automatic and puts files where users expect them - the Documents folder, visible in Finder/file explorer.
|
||||
|
||||
## Proposed Solution
|
||||
|
||||
Add a **Write tool step in SKILL.md** after the synthesis/stats/invitation block that saves the complete briefing to `~/Documents/Last30Days/{topic-slug}.md`. This is a SKILL.md-only change (no Python script modifications needed) because the content to save is the assistant's synthesized output, which only exists in the SKILL.md flow.
|
||||
|
||||
### Why SKILL.md, not the Python script
|
||||
|
||||
The Python script (`last30days.py`) runs first and produces raw scored items. The assistant then synthesizes these into the "What I learned" briefing, stats block, and invitation. The synthesis is the valuable part - it's what @devin_explores is saving. The script can't produce this because it runs before synthesis happens.
|
||||
|
||||
### File naming
|
||||
|
||||
Convert the TOPIC variable to a kebab-case slug for the filename:
|
||||
- "Claude Code best practices" -> `claude-code-best-practices.md`
|
||||
- "best rap songs 2026" -> `best-rap-songs-2026.md`
|
||||
- "nano banana 2 prompting guide" -> `nano-banana-2-prompting-guide.md`
|
||||
|
||||
This matches the screenshot pattern exactly (e.g., `anthropic-claude-code-best-practices.md`, `seedance-video-prompting-guide.md`).
|
||||
|
||||
If a file with the same slug already exists, append a date suffix: `claude-code-best-practices-2026-03-05.md`. This handles re-researching the same topic without overwriting previous results.
|
||||
|
||||
### File content
|
||||
|
||||
The saved .md file should contain the complete research output in this order:
|
||||
|
||||
```markdown
|
||||
# {TOPIC}
|
||||
|
||||
> Researched {date} | Query type: {QUERY_TYPE} | Target tool: {TARGET_TOOL or "general"}
|
||||
|
||||
## What I learned
|
||||
|
||||
{The full synthesis section - topics, patterns, citations}
|
||||
|
||||
## Stats
|
||||
|
||||
{The full stats box with source counts and engagement}
|
||||
|
||||
## Follow-up suggestions
|
||||
|
||||
{The 2-3 specific suggestions from the invitation block}
|
||||
|
||||
---
|
||||
*Generated by [last30days](https://github.com/mvanhorn/last30days-skill) v2.9*
|
||||
```
|
||||
|
||||
### Implementation location in SKILL.md
|
||||
|
||||
Insert a new section between the current "LAST - Invitation" display and the "WAIT FOR USER'S RESPONSE" section. The Write tool call happens silently - no user prompt, no opt-in. Just save and briefly confirm.
|
||||
|
||||
## Technical Considerations
|
||||
|
||||
- **Cross-platform paths**: `~/Documents/` exists on macOS and most Linux desktops. On systems where it doesn't exist, `mkdir -p` handles creation. Windows WSL users get it too.
|
||||
- **Permissions**: The Write tool in Claude Code can write to `~/Documents/` without issues. No sandbox concerns since this is the user's own Documents folder.
|
||||
- **Filename sanitization**: Strip special characters, collapse whitespace to hyphens, lowercase. Keep it simple - no need for a library, just basic string ops in the SKILL.md instructions.
|
||||
- **File size**: Based on the screenshot (9-34 KB files), the synthesis output is well within reasonable bounds.
|
||||
- **No opt-out flag needed initially**: This is the default behavior. If users complain, a `--no-save` flag can be added later. Start with always-on since the screenshot proves users want this.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] Running `/last30days {topic}` creates `~/Documents/Last30Days/{topic-slug}.md` automatically
|
||||
- [x] File contains: title, date, query metadata, full synthesis, stats block, follow-up suggestions
|
||||
- [x] Filename is kebab-case slug of the topic (e.g., `claude-code-skills-guide.md`)
|
||||
- [x] Duplicate topics get a date suffix instead of overwriting
|
||||
- [x] Directory `~/Documents/Last30Days/` is created automatically if it doesn't exist
|
||||
- [x] A brief confirmation line appears after the stats (e.g., "Saved to ~/Documents/Last30Days/claude-code-skills-guide.md")
|
||||
- [x] Agent mode (`--agent`) also saves the file
|
||||
- [x] No changes to the Python script - this is purely a SKILL.md addition
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Add save instructions to SKILL.md
|
||||
|
||||
Insert a new section after the invitation block (after line ~496, before "WAIT FOR USER'S RESPONSE" at line ~499):
|
||||
|
||||
**New section in `SKILL.md`:**
|
||||
|
||||
```markdown
|
||||
## Save Research to Documents
|
||||
|
||||
After displaying the invitation, save the complete research briefing:
|
||||
|
||||
1. Generate the filename from TOPIC:
|
||||
- Lowercase the topic
|
||||
- Replace spaces and special characters with hyphens
|
||||
- Remove consecutive hyphens
|
||||
- Trim to 60 characters max
|
||||
- Example: "Claude Code Best Practices" -> "claude-code-best-practices"
|
||||
|
||||
2. Check if file already exists. If so, append today's date:
|
||||
- "claude-code-best-practices.md" exists -> use "claude-code-best-practices-2026-03-05.md"
|
||||
|
||||
3. Use the Write tool to save to ~/Documents/Last30Days/{slug}.md with this content:
|
||||
- H1 title: the TOPIC
|
||||
- Metadata line: date, QUERY_TYPE, TARGET_TOOL
|
||||
- Full "What I learned" synthesis (everything you just displayed)
|
||||
- Full stats block
|
||||
- Follow-up suggestions from the invitation
|
||||
- Footer with skill attribution
|
||||
|
||||
4. Confirm briefly: "Saved to ~/Documents/Last30Days/{slug}.md"
|
||||
```
|
||||
|
||||
### Step 2: Update agent mode section
|
||||
|
||||
The `--agent` mode section (line ~116) skips interactive elements but should still save. Add a note that agent mode saves the file with the same logic.
|
||||
|
||||
### Step 3: Update Security & Permissions section
|
||||
|
||||
Add to the "What this skill does" list (line ~599):
|
||||
- "Saves research briefings as .md files to ~/Documents/Last30Days/"
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- Users accumulate a browsable library of .md research files in their Documents folder
|
||||
- No more manual copy-paste workflow to save results
|
||||
- Files are immediately findable in Finder/file explorer search
|
||||
|
||||
## Dependencies & Risks
|
||||
|
||||
- **Low risk**: Write tool is already in the skill's `allowed-tools` list
|
||||
- **Low risk**: ~/Documents/ is a standard, user-owned directory
|
||||
- **Edge case**: If the skill is interrupted mid-run (before synthesis), no file is saved - this is correct behavior since there's nothing to save yet
|
||||
- **Edge case**: Very long topics could produce unwieldy filenames - the 60-char truncation handles this
|
||||
|
||||
## Sources & References
|
||||
|
||||
- Screenshot from @devin_explores showing manual .md file library in ~/Documents/Last30Days/
|
||||
- Current output pipeline: `scripts/lib/render.py:798` (`write_outputs()`) writes to `~/.local/share/last30days/out/`
|
||||
- SKILL.md synthesis flow: lines 275-496 (internalize research -> show summary -> invitation)
|
||||
- Existing `--emit` modes: `scripts/last30days.py:1700` (`output_result()`)
|
||||
@@ -0,0 +1,253 @@
|
||||
# Partner Credits: Zero-Registration Free Tier for last30days Users
|
||||
|
||||
**Type:** Partnership proposal for ScrapeCreators
|
||||
**Date:** 2026-03-05
|
||||
**Status:** Draft proposal
|
||||
|
||||
---
|
||||
|
||||
## The Pitch
|
||||
|
||||
Every last30days user gets 100 free ScrapeCreators credits — Reddit, TikTok, Instagram — without ever visiting scrapecreators.com or creating an account. When they run out, the skill tells them where to upgrade. ScrapeCreators gets a distribution channel. last30days gets a killer default experience.
|
||||
|
||||
## The Problem
|
||||
|
||||
Right now, new last30days users hit a wall:
|
||||
|
||||
1. Install the skill (30 seconds)
|
||||
2. Try `/last30days AI video tools`
|
||||
3. Get told they need a `SCRAPECREATORS_API_KEY`
|
||||
4. Have to go to scrapecreators.com, register, get a key, paste it into `.env`
|
||||
5. Many never come back
|
||||
|
||||
The best Reddit experience requires a key. The friction kills adoption.
|
||||
|
||||
## The Proposal: Machine-Bound Partner Tokens
|
||||
|
||||
### How It Works
|
||||
|
||||
**ScrapeCreators side:**
|
||||
1. Issue last30days a **partner ID** (e.g., `partner_last30days`)
|
||||
2. Accept a new header: `X-Partner-Device: <device_hash>`
|
||||
3. On first request per device hash: allocate 100 credits, no registration needed
|
||||
4. Track usage: `(partner_id, device_hash) → credits_remaining`
|
||||
5. When credits hit 0: return `402` with upgrade URL in response body
|
||||
|
||||
**last30days side:**
|
||||
1. On first run, generate a **device fingerprint** and cache it locally
|
||||
2. If user has no `SCRAPECREATORS_API_KEY`, send requests with partner headers instead
|
||||
3. When 402 comes back, show a friendly "upgrade" message
|
||||
|
||||
That's it. No accounts, no OAuth, no registration flow.
|
||||
|
||||
### The Device Fingerprint
|
||||
|
||||
```python
|
||||
import hashlib, platform, uuid, os
|
||||
|
||||
def get_device_id():
|
||||
"""Generate a stable, hard-to-forge device fingerprint."""
|
||||
# Use the OS-level machine ID (persists across reinstalls on most systems)
|
||||
machine_id = _get_machine_id()
|
||||
|
||||
# Salt with the partner ID so the hash is useless outside this context
|
||||
raw = f"last30days:{machine_id}"
|
||||
return hashlib.sha256(raw.encode()).hexdigest()
|
||||
|
||||
def _get_machine_id():
|
||||
"""Get the OS hardware/machine ID."""
|
||||
if platform.system() == "Darwin":
|
||||
# macOS: IOPlatformUUID (hardware-bound, survives OS reinstall)
|
||||
import subprocess
|
||||
result = subprocess.run(
|
||||
["ioreg", "-rd1", "-c", "IOPlatformExpertDevice"],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
for line in result.stdout.splitlines():
|
||||
if "IOPlatformUUID" in line:
|
||||
return line.split('"')[-2]
|
||||
|
||||
elif platform.system() == "Linux":
|
||||
# Linux: /etc/machine-id (set at install time)
|
||||
try:
|
||||
return open("/etc/machine-id").read().strip()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
# Fallback: MAC address + hostname (less stable but reasonable)
|
||||
return f"{uuid.getnode()}:{platform.node()}"
|
||||
```
|
||||
|
||||
**Why this works:**
|
||||
- macOS `IOPlatformUUID` is hardware-bound — can't change it without a new motherboard
|
||||
- Linux `/etc/machine-id` is set at OS install — persists across reboots
|
||||
- Hashed with `last30days:` prefix so the raw ID is never sent to ScrapeCreators
|
||||
- Cached locally in `~/.config/last30days/.device_id` after first generation
|
||||
|
||||
### API Request Format
|
||||
|
||||
```
|
||||
# Without partner credits (existing flow — user has their own key)
|
||||
GET /v1/reddit/search?query=AI+tools
|
||||
x-api-key: sc_user_abc123
|
||||
|
||||
# With partner credits (new — no registration needed)
|
||||
GET /v1/reddit/search?query=AI+tools
|
||||
x-api-key: sc_partner_last30days
|
||||
X-Partner-Device: a1b2c3d4e5f6... (sha256 hex)
|
||||
```
|
||||
|
||||
ScrapeCreators treats `sc_partner_last30days` as a special key class:
|
||||
- Requires `X-Partner-Device` header
|
||||
- Credits tracked per device hash, not per API key
|
||||
- Rate limited per device (e.g., 10 requests/minute)
|
||||
- 100 credits per unique device, lifetime
|
||||
|
||||
### What Counts as a Credit
|
||||
|
||||
One API call = one credit. A typical `/last30days` run uses roughly:
|
||||
- 2-4 Reddit searches (global + subreddit drilldowns)
|
||||
- 1-2 TikTok searches + 2-3 transcript fetches
|
||||
- 1-2 Instagram searches + 2-3 transcript fetches
|
||||
|
||||
So ~10-15 credits per run. 100 credits ≈ **7-10 full research runs** before upgrade.
|
||||
|
||||
That's enough to get hooked.
|
||||
|
||||
## Abuse Prevention
|
||||
|
||||
### What we're defending against
|
||||
|
||||
| Threat | Likelihood | Impact |
|
||||
|--------|-----------|--------|
|
||||
| User spoofs device ID to get infinite credits | Low | Medium |
|
||||
| Script generates thousands of fake device IDs | Medium | High |
|
||||
| User shares partner key for non-last30days use | Low | Low |
|
||||
|
||||
### Defenses (simplest first)
|
||||
|
||||
**1. Hardware-bound device ID (primary defense)**
|
||||
- macOS IOPlatformUUID can't be changed without hardware swap
|
||||
- Linux machine-id requires root to change and breaks other software
|
||||
- Not a cookie or config file — it's the machine itself
|
||||
|
||||
**2. Rate limiting per device (ScrapeCreators side)**
|
||||
- 10 requests/minute per device hash
|
||||
- Prevents scripted rapid-fire abuse even with valid device IDs
|
||||
- Normal usage never hits this — a full run takes 60-70 seconds with natural gaps
|
||||
|
||||
**3. IP rate limiting on new device registrations (ScrapeCreators side)**
|
||||
- Max 3 new device hashes per IP per day
|
||||
- Stops "generate 1000 device IDs from one server" attacks
|
||||
- Legitimate users: one machine, one device ID, done
|
||||
|
||||
**4. Total partner pool cap (safety valve)**
|
||||
- ScrapeCreators sets a monthly cap on total partner credits (e.g., 50,000/month)
|
||||
- If last30days goes viral and blows the cap, both parties renegotiate
|
||||
- Prevents runaway costs from unexpected growth
|
||||
|
||||
### What we're NOT doing (intentional simplicity)
|
||||
|
||||
- No CAPTCHAs
|
||||
- No email verification
|
||||
- No phone verification
|
||||
- No browser fingerprinting
|
||||
- No token signing or crypto
|
||||
- No account creation whatsoever
|
||||
|
||||
The goal is zero friction. The device ID is "good enough" — it stops casual abuse and scripts. A determined attacker could maybe get 200-300 free credits by VM gymnastics, but that's not worth defending against when paid plans are cheap.
|
||||
|
||||
## User Experience
|
||||
|
||||
### First run (no key configured)
|
||||
|
||||
```
|
||||
$ /last30days AI video tools
|
||||
|
||||
🔍 Searching Reddit, TikTok, Instagram...
|
||||
ℹ️ Using 100 free partner credits from ScrapeCreators (93 remaining)
|
||||
Get your own key for unlimited use: scrapecreators.com/last30days
|
||||
|
||||
[... normal results ...]
|
||||
```
|
||||
|
||||
### Credits running low
|
||||
|
||||
```
|
||||
ℹ️ 12 partner credits remaining. Get unlimited access: scrapecreators.com/last30days
|
||||
```
|
||||
|
||||
### Credits exhausted
|
||||
|
||||
```
|
||||
⚠️ Free partner credits used up!
|
||||
|
||||
Reddit, TikTok, and Instagram require a ScrapeCreators API key.
|
||||
Get one at: scrapecreators.com/last30days (100 free credits on signup, then pay-as-you-go)
|
||||
|
||||
Continuing with X, YouTube, Hacker News, Polymarket, and web search...
|
||||
```
|
||||
|
||||
Key detail: the skill **doesn't stop working** — it gracefully falls back to the sources that don't need a key. The user still gets value, but they see what they're missing.
|
||||
|
||||
### After upgrade
|
||||
|
||||
```
|
||||
$ echo 'SCRAPECREATORS_API_KEY=sc_abc123' >> ~/.config/last30days/.env
|
||||
|
||||
# Next run — partner headers no longer sent, user's own key used
|
||||
```
|
||||
|
||||
## What ScrapeCreators Gets
|
||||
|
||||
1. **Distribution channel** — every last30days install is a potential paying customer
|
||||
2. **Zero support burden** — no accounts to manage for free tier users
|
||||
3. **Qualified leads** — users who exhaust 100 credits are proven power users
|
||||
4. **Co-marketing** — "Powered by ScrapeCreators" in every skill run
|
||||
5. **Usage data** — anonymous device-level usage patterns across topics
|
||||
|
||||
## What last30days Gets
|
||||
|
||||
1. **Zero-config Reddit** — install and go, no registration anywhere
|
||||
2. **TikTok and Instagram included** — three sources work out of the box
|
||||
3. **Lower barrier to adoption** — the #1 friction point eliminated
|
||||
4. **Upgrade path built in** — natural conversion funnel
|
||||
|
||||
## Implementation Effort
|
||||
|
||||
### ScrapeCreators side (their work)
|
||||
- [ ] Create partner key class with per-device credit tracking
|
||||
- [ ] Accept `X-Partner-Device` header on partner keys
|
||||
- [ ] Return `402` with upgrade URL when credits exhausted
|
||||
- [ ] Rate limit: 10 req/min per device, 3 new devices/day per IP
|
||||
- [ ] Dashboard for last30days to see aggregate partner usage
|
||||
|
||||
### last30days side (our work)
|
||||
- [ ] `scripts/lib/device_id.py` — generate and cache device fingerprint (~30 lines)
|
||||
- [ ] Update `scripts/lib/env.py` — fall back to partner auth when no user key
|
||||
- [ ] Update `_sc_headers()` in reddit.py, tiktok.py, instagram.py — add partner headers
|
||||
- [ ] Handle 402 response — show upgrade message, continue with other sources
|
||||
- [ ] Show credits remaining in run output (from response header)
|
||||
|
||||
### Suggested response headers from ScrapeCreators
|
||||
|
||||
```
|
||||
X-Partner-Credits-Remaining: 87
|
||||
X-Partner-Credits-Total: 100
|
||||
X-Partner-Upgrade-URL: https://scrapecreators.com/last30days
|
||||
```
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Credit pool negotiation** — what monthly cap works for ScrapeCreators?
|
||||
2. **Referral tracking** — should `scrapecreators.com/last30days` give a signup bonus or revenue share?
|
||||
3. **Credit count per endpoint** — should transcript fetches cost the same as searches?
|
||||
4. **Expiration** — do unused partner credits expire (e.g., 90 days)?
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
One device ID. One partner key. One header. 100 free credits. Zero registration.
|
||||
|
||||
The entire abuse prevention is: your computer has a hardware ID that you can't easily change. That's it. Simple, clever, and good enough.
|
||||
+4
-8
@@ -2,19 +2,15 @@ The AI world reinvents itself every month. This skill keeps you current.
|
||||
|
||||
`/last30days` researches your topic across **Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, and the web** from the last 30 days, finds what the community is actually upvoting, sharing, betting on, and saying on camera, and writes you a grounded narrative with real citations.
|
||||
|
||||
## What's New in v2.9.1
|
||||
|
||||
**Auto-save to ~/Documents/Last30Days/.** Every run now saves the complete research briefing - synthesis, stats, and follow-up suggestions - as a topic-named `.md` file to your Documents folder. Build a personal research library without lifting a finger. Inspired by [@devin_explores](https://x.com/devin_explores) who was already doing this manually.
|
||||
|
||||
## Three Headline Features in v2.9
|
||||
|
||||
**1. ScrapeCreators Reddit as default.** One `SCRAPECREATORS_API_KEY` now covers Reddit, TikTok, and Instagram - three sources, one key. No more `OPENAI_API_KEY` required for Reddit search. Faster, more reliable, and simpler to configure.
|
||||
**1. ScrapeCreators Reddit as default.** One `SCRAPECREATORS_API_KEY` now covers Reddit, TikTok, and Instagram — three sources, one key. No more `OPENAI_API_KEY` required for Reddit search. Faster, more reliable, and simpler to configure.
|
||||
|
||||
**2. Smart subreddit discovery.** Relevance-weighted scoring replaces pure frequency count. Each candidate subreddit is scored by `frequency x recency x topic-word match`, and a `UTILITY_SUBS` blocklist filters noise subs like r/tipofmytongue. Search "Claude Code skills" and get r/ClaudeAI, r/ClaudeCode, r/openclaw - not generic programming subs.
|
||||
**2. Smart subreddit discovery.** Relevance-weighted scoring replaces pure frequency count. Each candidate subreddit is scored by `frequency × recency × topic-word match`, and a `UTILITY_SUBS` blocklist filters noise subs like r/tipofmytongue. Search "Claude Code skills" and get r/ClaudeAI, r/ClaudeCode, r/openclaw — not generic programming subs.
|
||||
|
||||
**3. Top comments elevated.** The best comment on each Reddit thread now carries a 10% weight in engagement scoring and displays prominently with upvote counts. Reddit's value is in the comments - now the skill surfaces them.
|
||||
**3. Top comments elevated.** The best comment on each Reddit thread now carries a 10% weight in engagement scoring and displays prominently with `💬` and upvote counts. Reddit's value is in the comments — now the skill surfaces them.
|
||||
|
||||
Plus: **Instagram Reels** (v2.8), **Polymarket prediction markets** (v2.5), **YouTube transcripts** (v2.1), **bundled X search** - no external CLI needed.
|
||||
Plus: **Instagram Reels** (v2.8), **Polymarket prediction markets** (v2.5), **YouTube transcripts** (v2.1), **bundled X search** — no external CLI needed.
|
||||
|
||||
## Beta Test Results (v2.9)
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body { font-family: -apple-system, sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background: #f5f5f5; }
|
||||
.tweet { background: white; border-radius: 12px; padding: 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); white-space: pre-wrap; font-size: 15px; line-height: 1.5; }
|
||||
button { margin-top: 16px; padding: 10px 20px; background: #1d9bf0; color: white; border: none; border-radius: 20px; font-size: 14px; cursor: pointer; }
|
||||
button:hover { background: #1a8cd8; }
|
||||
.copied { background: #00ba7c; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="tweet" id="tweet">/last30days v2.9 is out. Reddit just got a massive upgrade.
|
||||
|
||||
Top comments are now first-class. The best comment on each thread gets 10% scoring weight and shows up like:
|
||||
|
||||
r/ClaudeAI — "Anthropic Released 32 Page Detailed Guide on Building Claude Skills" [1,470pts, 112 comments]
|
||||
💬 Top comment (567 pts): "Can't wait to have Claude read this and explain it to me."
|
||||
|
||||
Reddit's value was always in the comments. Now the skill actually reads them.
|
||||
|
||||
The other big change: smart subreddit discovery. It scores every candidate by frequency × recency × topic-word match and blocklists utility subs that used to pollute results.
|
||||
|
||||
Before: search "Kanye West" → r/AskReddit, r/OutOfTheLoop
|
||||
Now: r/hiphopheads, r/Kanye, r/NFCWestMemeWar
|
||||
|
||||
Shoutout to @ScrapeCreators — one API key now covers Reddit, TikTok, and Instagram. Three sources, one key. Should be cheaper than using an OpenAI key too.</div>
|
||||
<button onclick="copyTweet()">Copy to clipboard</button>
|
||||
<script>
|
||||
function copyTweet() {
|
||||
const text = document.getElementById('tweet').textContent;
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
const btn = document.querySelector('button');
|
||||
btn.textContent = 'Copied!';
|
||||
btn.classList.add('copied');
|
||||
setTimeout(() => { btn.textContent = 'Copy to clipboard'; btn.classList.remove('copied'); }, 2000);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user