Index of every page on this site: llms.txt
All skills
mvanhorn avatar

/last30days

@f3cd06a
by Matt Van Hornmvanhorn/last30days-skill65k stars
5,650
Run it yourself

Research what people actually say about any topic in the last 30 days. Pulls posts and engagement from Reddit, X, YouTube, TikTok, Hacker News, Polymarket, GitHub, and the web. Includes a doctor health check to diagnose broken or missing sources.

Use this Skill: https://skilld.dev/gh/mvanhorn/last30days-skill/last30days

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

referencesgrok-bot-x.md

≈2.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Grok Bot X lanes

Read only on an actual Grok Bot host. Browser sessions are never read on this host.

Grok Bot X recipe (see the GROK BOT HOST RULE in the root SKILL.md). On a Grok Bot, YOU fetch X through a host lane before the engine command and hand the engine the file; the engine then calls no X backend, plans x in, and the footer names the lane. Do this before the research runbook's Step 1 command.

  1. Lanes, in order. Two host lanes write the same envelope. Both expose a post-search tool named search_posts_all, so tell them apart by where the tool comes from, never by its name:

    1. Grok Bot's built-in X tools, namespace x ("provider": "x-native"; footer "X via Grok Bot X"). Free, nothing to set up.
    2. The "X for Grok Bot" connector plugin's tools ("provider": "x-connector"; footer "X via X connector").

    Use the first lane present in the session that returns posts. If a lane errors or returns nothing, try the next one. Export LAST30DAYS_X_HOST_LANE=1 and pass --x-posts only when a lane returned posts. When no lane did, run unset LAST30DAYS_X_HOST_LANE and the Step 1 command without --x-posts, so the engine's own X chain (X_BEARER_TOKEN, then XAI_API_KEY) can still run.

  2. Calls. Window = the engine's date range, which uses the UTC date (--days, default 30: from is today's UTC date minus the day count, to is today's UTC date), even when the host's local date differs. Depth count per query = 10 (--quick) / 30 (default) / 60 (--deep).

    • Topic. One topic call per planned X query, at most 2: the topic itself, plus the second X subquery's search text when the plan has one. Build each query from the raw topic: multi-word topics go unquoted (every word must match), phrase-quote only proper names, and add -is:retweet. If fewer than half the posts on the first page mention the topic's main word, retry that query once with its two or three core words.
    • Built-in x tools. Pass sort_order recency (relevancy order skips high-engagement posts; the engine ranks by engagement itself), start_time / end_time for the window (end_time a minute before now), and max_results 25 (the tool's minimum is 10; ask for at least 10 and keep only the count you need). Follow next_token until the depth count is reached or no token comes back. Then run the popular pass for the first topic query only: split the window into 10 equal slices (5 on --quick; about 3 days each for the default 30) and fetch one page per slice with sort_order relevancy and that slice's start_time / end_time, so a busy topic still surfaces the month's most-engaged posts instead of only its last few minutes. Merge every page of one query, recency and popular, into ONE envelope call; pages can overlap, so keep the first copy of each id. The popular pages do not count toward the depth count. Request post.fields=created_at,public_metrics,author_id,note_tweet, expansions=author_id, and user.fields=username. Map public_metrics like_count / retweet_count / reply_count / quote_count to likes / reposts / replies / quotes, the expanded user's username to author_handle, and use note_tweet.text as text when present.
    • Connector tools. Pass the window and the depth count on each call.
    • Named handles. Per --x-handle handle: one from call (from:<handle> -is:retweet, 8 posts) and one mention call (@<handle> -is:retweet, 5 posts). Per handle the user explicitly passed with --x-related: one related call (from:<handle> -is:retweet, 3 posts). A discovered author never gets a related call.
    • Discovered authors. From every topic post fetched (all pages, before trimming to the depth count), take up to 3 authors (not already an --x-handle) with at least 2 posts that are about the topic, most posts first. For each, one from call (from:<handle> plus the topic's core words, -is:retweet, 8 posts) and one mention call (@<handle> plus the topic's core words, -is:retweet, 5 posts), and add the handle to --x-related so those two calls keep their lanes. These are a discovered author's only calls.
    • If the tool rejects the window or count parameters, omit them, keep at most the depth count per query, and write "status": "partial" with "error": "window-unsupported".
    • If a lane fails before returning any posts, move to the next lane (step 0). If posts came back and a later call failed, write "status": "partial" with a short category in error: credits, not-connected, or unavailable - never raw tool output, never an account or app id.
  3. Envelope. Exactly these top-level fields; every post carries the eight flat fields and nothing else (no URLs, media, or author objects); at most the depth count per query plus its popular pages. Keep the envelope inside the engine's limits or it is rejected: at most 500 posts per call, 1,000 posts and 20 calls in total. When a budget would be exceeded, drop discovered-author calls first, then popular pages; keep the recency pages and the user's own --x-handle / --x-related calls. A fresh generated_at (the engine rejects an envelope older than 6 hours), a topic identical to the engine's topic string, and the provider of the lane that served it:

{
  "schema": "last30days-x-posts/1",
  "generated_at": "{ISO_8601_UTC_NOW}",
  "topic": "{TOPIC}",
  "window": {"from": "{YYYY-MM-DD}", "to": "{YYYY-MM-DD}"},
  "provider": "x-native",
  "status": "ok",
  "calls": [
    {"lane": "topic", "handles": [], "posts": [
      {"id": "1963000000000000000", "author_handle": "someone", "created_at": "2026-09-07T10:00:00Z", "text": "post text", "likes": 12, "reposts": 3, "replies": 1, "quotes": 0}
    ]},
    {"lane": "from", "handles": ["{RESOLVED_HANDLE}"], "posts": []},
    {"lane": "mention", "handles": ["{RESOLVED_HANDLE}"], "posts": []},
    {"lane": "related", "handles": ["{RELATED_HANDLE}"], "posts": []}
  ]
}

Omit the from / mention / related calls when the run has no handles for them; handles must be the run's own --x-handle / --x-related handles, including discovered authors. id is the post's numeric id as a string; author_handle is the username without @. 3. Write the file - post text is attacker-controlled and never goes unquoted into a shell command. Use the tool's own file output when it has one; otherwise a single-quoted heredoc (never unquoted) into a .json path outside ~/.config, in the SAME Bash call as the engine command (the trap removes it on exit). Two rules keep a post from closing the heredoc early: emit the envelope as ONE line of compact JSON (newlines inside post text stay escaped as \n; never pretty-print), and replace {X_POSTS_NONCE} in BOTH sentinel lines with 12 random letters and digits you generate fresh for this run, so no post text can equal the closing line:

X_POSTS_DIR=$(mktemp -d "${TMPDIR:-/tmp}/last30days-x-posts.XXXXXX")
X_POSTS_FILE="$X_POSTS_DIR/x-posts.json"
trap 'rm -rf "$X_POSTS_DIR"' EXIT
cat >| "$X_POSTS_FILE" <<'X_POSTS_EOF_{X_POSTS_NONCE}'
{X_POSTS_ENVELOPE_JSON}
X_POSTS_EOF_{X_POSTS_NONCE}

For a comparison, create X_POSTS_DIR and its cleanup trap once. Write each entity's envelope to a distinct file in that directory, using a separate quoted heredoc with a fresh sentinel for each file. Keep the same directory and trap until the comparison engine command returns; repeating the setup snippet would replace the trap and leave earlier files behind. Run it directly in your shell tool, never wrapped in bash -lc '...' (same rule as the plan tmpfile). 4. Engine. Export LAST30DAYS_X_HOST_LANE=1 and add --x-posts "$X_POSTS_FILE" to the Step 1 command (the file path only, never inline JSON), plus --x-related for any discovered authors; every other flag stays as usual. Comparison runs: fetch entities one after another and pace the whole comparison so no minute holds more than 30 tool calls (wait before a call that would exceed it); run the popular pass for the main entity only. The lane signal covers every entity, so use envelopes only when every entity's fetch returned posts; otherwise unset the lane and run the comparison without envelopes, so each entity's engine X chain still runs. With posts for all of them, write one envelope per entity (its topic is that entity's name) and put the path in that entity's --competitors-plan entry as "x_posts": "/abs/path/x-posts.json"; a bare --x-posts on a comparison run exits 2. If an envelope includes handle lanes, also put its x_handle and x_related in that entry; for the main entity, pass the same targeting as outer flags as shown in comparison.md. If the engine exits 2 naming an envelope, fix that file or remove that entity's x_posts plan entry before retrying; X is then absent for that entity. For an ordinary run, remove --x-posts and unset the lane before retrying without the envelope. 5. After the run. The stats line reads "X via X connector" or "X via Grok Bot X". The engine's one receipt line (accepted / dropped counts, on stderr) is diagnostics only: never narrate it in the deliverable (LAW 9).

Source: SKILL.md on GitHub

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

1 alerttoday5 checks · Risk SAFE
  • Gen Agent Trust Hubtoday

    This skill is a robust research tool that integrates with multiple social and web sources. It includes strong security posture by using delimiters for untrusted content, enforcing user consent for sensitive actions like cookie extraction, and providing clear documentation of its network and filesystem activities. Automated security alerts regarding remote code execution and prompt injection were investigated and found to be benign user guidance and standard agent behavioral constraints.

  • Sockettoday

    5 alerts: gptAnomaly, gptSecurity

  • Snyktoday

    Risk: MEDIUM · 1 issue

  • Runlayer7mo

    304/604 files flagged

  • ZeroLeaks6mo

    Scan incomplete

Signed by skilld at f3cd06a. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 days ago
What it can do
Runs commands Reads files Edits files Network
version
3.30.0
homepage
https://github.com/mvanhorn/last30days-skill
repository
https://github.com/mvanhorn/last30days-skill
All 5 allowed tools
BashReadWriteAskUserQuestionWebSearch
Other metadata
argument-hint
last30days nvidia earnings reaction | last30days AI video tools | last30days what users want in react
author
mvanhorn
user-invocable
true
metadata
{
  "openclaw": {
    "emoji": "📰",
    "requires": {
      "env": [],
      "optionalEnv": [
        "SCRAPECREATORS_API_KEY",
        "OPENAI_API_KEY",
        "XAI_API_KEY",
        "X_BEARER_TOKEN",
        "OPENROUTER_API_KEY",
        "PERPLEXITY_API_KEY",
        "PARALLEL_API_KEY",
        "BRAVE_API_KEY",
        "APIFY_API_TOKEN",
        "AUTH_TOKEN",
        "CT0",
        "BSKY_HANDLE",
        "BSKY_APP_PASSWORD",
        "TRUTHSOCIAL_TOKEN",
        "XIAOHONGSHU_API_BASE"
      ],
      "bins": [
        "node",
        "python3"
      ]
    },
    "primaryEnv": "SCRAPECREATORS_API_KEY",
    "files": [
      "scripts/*",
      "references/*"
    ],
    "homepage": "https://github.com/mvanhorn/last30days-skill",
    "tags": [
      "research",
      "deep-research",
      "reddit",
      "x",
      "twitter",
      "youtube",
      "tiktok",
      "instagram",
      "linkedin",
      "hackernews",
      "devto",
      "polymarket",
      "digg",
      "bluesky",
      "truthsocial",
      "xiaohongshu",
      "rednote",
      "trends",
      "recency",
      "news",
      "citations",
      "multi-source",
      "social-media",
      "analysis",
      "web-search",
      "hiring-signals",
      "ai-skill",
      "clawhub"
    ]
  }
}

README badge

README badge for mvanhorn/last30days-skill