Monitor external web and social mentions of the operator's active projects - surface what people are discovering, where they're confused, and where to engage
Monitor external web and social mentions of the operator's active projects - surface what people are discovering, where they're confused, and where to engage
schedule
25 7 2/2 * *
commits
false
permissions
[]
var
tags
["social","dev"]
requires
["XAI_API_KEY?"]
${var} — Comma-separated project names to track (e.g. "MyApp, my-lib"). If empty, derives targets from MEMORY.md and memory/topics/projects.md.
Read memory/MEMORY.md for current project status.
Read the last 3 days of memory/logs/ to avoid re-surfacing already-noted mentions.
Steps
Define the targets.
If ${var} is set: parse it as a comma-separated list of project names.
Otherwise: scan memory/MEMORY.md (goals, active topics) and memory/topics/projects.md (if it exists) for the operator's active projects. A target needs at least a name; collect a site/domain and a GitHub owner/repo too when known.
Cap at 6 targets — prefer the most active ones.
If zero targets can be derived: log MENTION_RADAR_SKIP: no projects configured — set var or add projects to memory/topics/projects.md and stop. No notification.
For each target, build search terms:
The exact project name in quotes (e.g. "MyApp" site:x.com OR site:reddit.com OR site:news.ycombinator.com)
The domain if known (e.g. "myapp.xyz")
The repo if known (e.g. site:github.com owner/myapp)
Search for external mentions. X/Twitter is fetched via the X.AI Responses API (primary); the rest of the public web (Reddit, Farcaster, blogs, newsletters, GitHub Discussions, HN, Product Hunt) goes through WebSearch, which is also the last-resort fallback for X itself. Derive the operator's handle from soul/SOUL.md if present (call it $OPERATOR) so you can exclude their own posts.
Path A — X.AI API (primary, X/Twitter mentions). For each target, ask Grok's x_search who is talking about the project on X. See the Fetching contract below — attempt this whenever the key is present, set the Bash tool timeout to ≥180000, and capture the HTTP status. Use a unique tmp filename per target if you loop (e.g. /tmp/xai-mr-$SLUG.json). $NAME/$DOMAIN/$REPO come from the target built in step 1 ($DOMAIN/$REPO may be empty — leave them out if so):
"Search X for posts by OTHER people mentioning the project \"${NAME}\" (also its site ${DOMAIN} and repo ${REPO} when given), posted between ${FROM_DATE} and ${TO_DATE}. Exclude posts by the operator @${OPERATOR} and by the project's own accounts. For each mention return: @handle, the full post text, date, exact engagement counts (likes, retweets, replies; 0 if unknown), the poster's approximate follower count if visible, and the direct link https://x.com/handle/status/ID. Prioritize people discovering it for the first time, asking confused questions, hitting friction (setup/docs/missing feature), comparing it to a competitor, or requesting a feature. Return a numbered list; if nobody is talking about it, say so explicitly."
On HTTP=200 with a non-empty body, parse /tmp/xai-mr.json with jq -r '.output[] | select(.type == "message") | .content[] | select(.type == "output_text") | .text' and feed the X mentions into categorization (step 4). Record X_SOURCE=api.
Path B — WebSearch (broader web + X fallback). Always use WebSearch for the non-X surfaces — Reddit, Farcaster, personal blogs, newsletters, GitHub Discussions, HN, Product Hunt:
Try both brand name and URL variants
Time-box to last 7 days where the search engine supports it
Skip results from the operator's own accounts and the project's own repos
WebSearch is also the fallback for X/Twitter, but only when Path A truly failed (key-unset, http-<code>, empty, or timeout — record the real reason per the Fetching contract, never "XAI_API_KEY unavailable" when the key was set). On the X fallback query site:x.com "<project name>" after:${FROM_DATE}; note in the log that X results came from WebSearch (lower quality) and set X_SOURCE=websearch.
Also check GitHub network signals for each target with a known repo:
gh api repos/OWNER/REPO --jq '{stars: .stargazers_count, forks: .forks_count, watchers: .watchers_count}'
Skip any repo that 404s (private or not yet public). Compare to the last log entry to compute deltas. If no prior data, record as baseline.
Categorize each mention found:
Discovery — person found the project for the first time, sharing it, impressed ("this is cool", star notification, share)
Confusion — person unclear on what it does, asking questions, mischaracterizing it
Friction — person ran into a problem (setup, docs, missing feature)
Competitor comparison — mentioned alongside or against a competing project
Feature request / wish — explicit ask for something missing
Press / newsletter — cited in a publication or digest
Identify engagement opportunities. Flag any mention where:
The person is confused and a 1-tweet clarification would help
A feature request aligns with what's being built
A competitor comparison is wrong or incomplete
A high-follower account discovered the project (high-leverage reply opportunity)
Format the output (under 4000 chars):
*Mention Radar — ${today}*
{PROJECT NAME, uppercased}
- [source] — [what they said] — [category]
...
(one section per target)
ENGAGEMENT OPPORTUNITIES
- [handle/source]: [why worth replying]
QUIET: [project] — no external mentions found
Use QUIET: [project] for any project with zero external mentions this cycle.
Skip GitHub-only star delta if it's less than 5 — only mention notable jumps.
Only notify if there's signal. Skip notification if ALL projects are quiet and no GitHub deltas > 5 stars. Log MENTION_RADAR_QUIET instead.
Send via ./notify if there's anything worth surfacing.
Log to memory/logs/${today}.md:
## Mention Radar
- **{project}:** [N mentions / QUIET]
(one line per target)
- **Top find:** [best mention in one line, or "none"]
- **Engagement opps:** [N flagged, or 0]
- **Notification sent:** yes/no
Guidelines
This is signal filtering, not a metrics report. One real conversation > ten impressions.
Prioritize quality of mention over quantity. A thoughtful Reddit post or HN comment matters more than a retweet.
Don't manufacture urgency. If there's nothing worth acting on, say so.
Be specific — link the source, quote the key line, name the person if identifiable.
The point is engagement opportunity and awareness, not vanity numbers.
Fetching
XAI_API_KEY is injected into your environment for this skill (declared in requires:). It is present and valid. The primary fetch path for X/Twitter mentions is a direct curl to https://api.x.ai/v1/responses with Authorization: Bearer {XAI_API_KEY} (step 2, Path A). There is no network sandbox blocking this; earlier versions of this skill claimed there was — that is stale and wrong. Just make the call.
You MUST attempt the direct curl before any X fallback. The rules:
Check, don't assume. Run [ -n "$XAI_API_KEY" ] && echo KEY_PRESENT || echo KEY_UNSET. If KEY_PRESENT (it will be), you are required to try Path A.
Allow enough time. The x_search call typically takes 30–120s (it searches X live). When you invoke the Bash tool for the curl, set the tool's timeout to at least 180000 (180s), and keep --max-time 150 on the curl itself so it fails cleanly rather than hanging. A curl that is slow is not a missing key — do not treat a timeout as "key unavailable".
Capture the HTTP status so the fallback decision is based on fact, not assumption. Build the payload to the fixed file /tmp/xai-mr-payload.json first (the jq -n --arg in Path A), then send it with -d @file — the ./secretcurl command must stay 100% literal (no $VAR):
Then parse /tmp/xai-mr.json with the standard jq extractor. HTTP=200 with a non-empty body → use it (X_SOURCE=api).
Fall back only on a real failure, and record the true reason — never write "XAI_API_KEY unavailable" when the key was set. Use one of: key-unset (only if step 1 said KEY_UNSET), http-<code> (non-2xx), empty (200 but no mentions parsed), timeout (curl exceeded --max-time).
WebSearch / WebFetch are last-resort fallbacks only for X — lower quality (WebSearch favours old high-engagement tweets). They remain the primary tool for the non-X web surfaces (Reddit, HN, blogs, etc.). Never reach for the X WebSearch fallback while the key works.
Environment Variables
XAI_API_KEY — X.AI API key for Grok's x_search tool. Declared in requires: (optional ?), so it is injected into this skill's environment and is the primary path for X/Twitter mentions. If it is ever unset, X mentions degrade to the WebSearch fallback at lower quality; the broader-web search is unaffected.
gh CLI — pre-authenticated in GitHub Actions; used for the GitHub network-signal check (step 3). Not an env var you set here.