Skip to content
Agentmart
Submit a tool

last30

Cross-platform social research - narrative-first intelligence on what people are saying about a topic across Reddit, X, HN, Polymarket, and the web over the…

Skill by aeonfun

IndexedMIT★ 782
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/aeonfun-last30

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Cross-platform social research - narrative-first intelligence on what people are saying about a topic across Reddit, X, HN, Polymarket, and the web over the last 30 days

Use cases: research

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/last30

What's inside

Skill name
last30
Description
Cross-platform social research - narrative-first intelligence on what people are saying about a topic across Reddit, X, HN, Polymarket, and the web over the last 30 days
License
MIT
Metadata
var: · title: Last 30 Days · category: basics
Instructions
384 lines in SKILL.md · view on GitHub

Before installing

  • Instructions call the network

Files (1)

  • SKILL.md

SKILL.md (first lines)

<!-- autoresearch: variation B — narrative-first output with sentiment splits, contrarian view, and what-changed delta -->

> **${var}** — Topic to research (required). Append `--quick` for a lighter pass (≤15 sources), or `--days=N` to change the lookback window (default: 30).

Google aggregates editors. A flat "top N posts per platform" aggregates noise. This skill does two things differently: (1) reframes output around **narratives** (clusters the same story across platforms) instead of platform-siloed recaps, and (2) makes the **disagreement** between platforms the primary signal — where Reddit is bearish and X is bullish on the same story, that divergence is usually the most actionable finding.

If `${var}` is empty, abort and notify: `"last30 requires var= set to a topic"`. Exit.

---

## Steps

### 0. Parse parameters and bootstrap

Extract from `${var}`:
- **topic**: everything before any `--` flags, trimmed
- **--quick**: lighter mode (fewer sources, shorter report)
- **--days=N**: custom lookback window (default: 30)

```bash
DAYS=30  # or from --days flag
FROM_DATE=$(date -u -d "${DAYS} days ago" +%Y-%m-%d 2>/dev/null || date -u -v-${DAYS}d +%Y-%m-%d)
TO_DATE=$(date -u +%Y-%m-%d)
FROM_TS=$(date -u -d "${FROM_DATE}" +%s 2>/dev/null || date -u -j -f "%Y-%m-%d" "${FROM_DATE}" +%s)
YEAR=$(date -u +%Y)
TODAY=$(date -u +%Y-%m-%d)
TOPIC_SLUG=$(echo "$TOPIC" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+|-+$//g')
```

Read `memory/MEMORY.md` for tracked interests.
Read `memory/topics/last30-${TOPIC_SLUG}.md` if it exists — it holds the prior snapshot used for the **What Changed** section below. If absent, this is a cold run.
Read the last 3 `memory/logs/` entries to avoid duplicating very recent work on the same topic.

---

### 1. Entity pre-resolution

Run 2-3 WebSearches to discover the right handles, communities, and terms. Do this **before** platform queries — searching blind across wrong subreddits wastes sources.

```
WebSearch: "${topic}" site:reddit.com
WebSearch: "${topic}" site:x.com OR site:twitter.com
WebSearch: "${topic}" community OR subreddit OR forum OR "best account"
```

Extract:
- **2-4 relevant subreddits** (note the exact lowercase name, e.g. `solana`, `cryptocurrency`)
- **2-3 relevant X handles** (voices with demonstrated signal on this topic)
- **2-3 search variants** (alternate names, abbreviations, hashtags)
- **Anchor tokens**: proper nouns, project names, specific numbers, URL domains that identify the topic. These are used for clustering in step 7.

Write the resolved entities to a scratch variable — you'll pin them into every downstream prompt to prevent topic drift.

---

### 2. Reddit search (30-day window)

**Fetch note**: Reddit public `.json` works unauthenticated but caps at ~10 req/min per IP and **requires a descriptive User-Agent** or it returns empty `{}` 200s. If curl fails or returns empty, use **WebFetch** on the same URL.

User-Agent format: `aeon-bot:last30:v1 (by /u/aeon-agent)`

For each identified subreddit (up to 4), fetch top posts from the window using `old.reddit.com`:

```bash
UA="aeon-bot:last30:v1 (by /u/aeon-agent)"
# Subreddit-restricted top-of-month
curl -sL -A "$UA" \
  "https://old.reddit.com/r/${SUBREDDIT}/search.json?q=${TOPIC_ENC}&restrict_sr=on&sort=top&t=month&limit=15"
```

Broad cross-subreddit search:
```bash
curl -sL -A "$UA" \
  "https://old.reddit.com/search.json?q=${TOPIC_ENC}&sort=top&t=month&limit=25"
```

**Empty-result detection**: if `data.children.length == 0` on a 200 response, that's a rate-limit, not a real empty. Back off 10s, retry once. If still empty, fall back to WebFetch on the same URL.

Extract per post: `title`, `selftext` (first 500 chars), `score`, `num_comments`, `permalink` (build full URL), `created_utc`, `subreddit`, `url` (the external link if any — captured for canonical-URL dedup in step 7).

**Quick mode:** broad search only, 15 posts.
**Full mode:** all identified subreddits + broad search. For the top 3-5 threads by `score + num_comments`, fetch top comments:
```bash
curl -sL -A "$UA" \
  "https://old.reddit.com/r/${SUBREDDIT}/comments/${POST_ID}.json?sort=top&limit=10"
```

**Topic-drift guard**: discard any post whose title + first 200 chars of selftext contains none of the topic terms or entity anchors from step 1.

---

### 3. X / Twitter (30-day window)

`XAI_API_KEY` is **injected into this skill's environment** (declared in `requires:`) and is present and valid. The **primary** X source is a direct `curl` to `https://api.x.ai/v1/responses` — there is no network sandbox. See **## Fetching** for the full contract (timeout, HTTP capture, fallback taxonomy). WebSearch is a last-resort fallback only.

**Path A — X.AI API (primary).** Confirm the key, then run the topic-window query. Set the Bash tool `timeout` to **≥180000** (x_search takes 30–120s); the curl carries `--max-time 150`. A slow curl is **not** a missing key — never treat a timeout as key-unavailable.

```bash
[ -n "$XAI_API_KEY" ] && echo KEY_PRESENT || echo KEY_UNSET   # prints KEY_PRESENT — Path A is required
# Build the payload to a file with jq --arg (no heredoc into a var) so the ./secretcurl command stays 100% literal:
jq -n --arg topic "$TOPIC" --arg variants "$SEARCH_VARIANTS" --arg fd "$FROM_DATE" --arg td "$TO_DATE" \
  '{model:"grok-4.7", input:[{role:"user",content:("Search X for tweets about: "+$topic+" (also try: "+$variants+"). Date range: "+$fd+" to "+$td+". Return 15-25 substantive tweets - mix high-engagement posts with smaller accounts that add a distinct angle. For each: @handle, full text, date posted, exact engagement counts (likes, retweets, replies; 0 if unknown), follower count if available, and the direct link https://x.com/handle/status/ID. Skip retweets and reply-guy near-duplicates.")}], tools:[{type:"x_search",from_date:$fd,to_date:$td}]}' \
  > /tmp/xai-last30-topic-payload.json
HTTP=$(./secretcurl -s -o /tmp/xai-last30-topic.json -w '%{http_code}' --max-time 150 -X POST "https://api.x.ai/v1/responses" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {XAI_API_KEY}" \
  -d @/tmp/xai-last30-topic-payload.json)
echo "xai http=$HTTP bytes=$(wc -c </tmp/xai-last30-topic.json)"
```

On `HTTP=200` with a non-empty body, set `X_STATUS=api` and parse with the standard extractor:
```bash
jq -r '.output[]|select(.type=="message")|.content[]|select(.type=="output_text")|.text' /tmp/xai-last30-topic.json
```

**Full mode — handle-restricted second call.** Using the 2-3 X handles resolved in step 1, issue a second call scoped to them (the handles are named directly in the prompt; unique tmp filename so it doesn't clobber the topic call):
```bash
# Build the handle-restricted payload to its own file with jq --arg (keeps the ./secretcurl command literal):
jq -n --arg topic "$TOPIC" --arg handles "$RESOLVED_HANDLES" --arg fd "$FROM_DATE" --arg td "$TO_DATE" \
  '{model:"grok-4.7", input:[{role:"user",content:("Search X for tweets from these accounts about "+$topic+": "+$handles+". Date range: "+$fd+" to "+$td+". For each: @handle, full text, date, engagement counts (likes, retweets, replies; 0 if unknown), and the direct link https://x.com/handle/status/ID.")}], tools:[{type:"x_search",from_date:$fd,to_date:$td}]}' \

From aeonfun/aeon, MIT.

More from aeonfun/aeon

Compare and alternatives

    Featured in

    Signals

    Stars
    782
    Forks
    292
    Open issues
    0
    Last commit (this folder)
    Oct 1, 2026 (26 days ago)
    Last release
    Jul 9, 2026 (3 months ago)

    From GitHub (fetched Oct 24, 2026).

    Details

    License
    MIT
    First seen
    Oct 24, 2026
    Last checked
    Oct 24, 2026

    More from aeonfun

    Cite this page

    last30 skill. Agent Mart. https://agentmart.dev/skills/aeonfun-last30 (last updated 2026-10-24)