[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6J4FVCC35G2RNECPRD20M94":3,"skill-same:01M6J4FVCC35G2RNECPRD20M94":71},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":35,"linkOnly":36,"markdownContent":37,"markdownBody":38,"frontMatter":39,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":52,"ownerHtmlUrl":53,"ownerBlogUrl":54,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M6J4FVCC35G2RNECPRD20M94","mention-radar",null,"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","MiroShark\u002Fmiroshark-aeon","MiroShark","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F304594232?v=4","01M6J466B8NNAZ4H6NNK3N3TT5","01M6J466FXNNWH622S3B9PC496",20,"MIT","https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fmention-radar\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],"mention radar","radar","engage","operator","xai","active","web","productivity","api","false","people","dev","monitor","twitter","social","re","projects","2026-11-10 10:12:30",false,"---\nname: mention-radar\ndescription: 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\nmetadata:\n  title: Mention Radar\n  category: productivity\n  commits: false\n  var: \"\"\n  tags:\n    - social\n    - dev\n  requires:\n    - TWITTER_API_KEY\n    - XAI_API_KEY?\n---\n> **${var}** — Comma-separated project names to track (e.g. \"MyApp, my-lib\"). If empty, derives targets from MEMORY.md and memory\u002Ftopics\u002Fprojects.md.\n\nRead memory\u002FMEMORY.md for current project status.\nRead the last 3 days of memory\u002Flogs\u002F to avoid re-surfacing already-noted mentions.\n\n## Steps\n\n1. **Define the targets.**\n   - If `${var}` is set: parse it as a comma-separated list of project names.\n   - Otherwise: scan `memory\u002FMEMORY.md` (goals, active topics) and `memory\u002Ftopics\u002Fprojects.md` (if it exists) for the operator's active projects. A target needs at least a name; collect a site\u002Fdomain and a GitHub `owner\u002Frepo` too when known.\n   - Cap at 6 targets — prefer the most active ones.\n   - If zero targets can be derived: log `MENTION_RADAR_SKIP: no projects configured — set var or add projects to memory\u002Ftopics\u002Fprojects.md` and stop. No notification.\n\n   For each target, build search terms:\n   - The exact project name in quotes (e.g. `\"MyApp\" site:x.com OR site:reddit.com OR site:news.ycombinator.com`)\n   - The domain if known (e.g. `\"myapp.xyz\"`)\n   - The repo if known (e.g. `site:github.com owner\u002Fmyapp`)\n\n2. **Search for external mentions.** X\u002FTwitter is fetched via **twitterapi.io** (**primary**); xAI Grok `x_search` is the fallback; 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\u002FSOUL.md` if present (call it `$OPERATOR`) so you can exclude their own posts.\n\n   **Shell shape.** Each Bash call is one allowed command (pipes are fine). The run refuses a call that sets a variable (`FROM_DATE=$(date ...)`, `Q=\"...\"`, `HTTP=$(.\u002Fsecretcurl ...)`), uses `if` \u002F `for` \u002F `while` or `[ -n ... ] &&` tests, or joins commands with `;`, `&&` or `||`, and each refusal costs a model turn. So get a date with a bare `date` call and write the printed value into later commands; write each target's name, domain, repo, the operator handle and the dates into each command literally (the `\u003CNAME>`, `\u003CFROM_DATE>` style placeholders in the snippets), jq filters included (a jq `$name` variable from `--arg` is refused, and so is a `>` redirect into a file, so the xAI body is piped straight into `.\u002Fsecretcurl ... --data-binary @-`); loop over targets by making one call per target; run one `jq` per call.\n\n   Get the window dates first, each `date` as its own Bash call:\n   ```bash\n   date -u -d '7 days ago' +%Y-%m-%d\n   ```\n   ```bash\n   date -u +%Y-%m-%d\n   ```\n   The first prints FROM_DATE, the second TO_DATE.\n\n   **Path A - twitterapi.io (primary, X\u002FTwitter mentions).** For each target, structured search for other people mentioning the project. See the **Fetching** contract below. Use a unique tmp filename per target if you loop (e.g. `\u002Ftmp\u002Ftw-mr-\u003CSLUG>.json`). `\u003CNAME>`\u002F`\u003CDOMAIN>`\u002F`\u003CREPO>` come from the target built in step 1, written in literally. Put the date window inside the query with `since:`\u002F`until:`; exclude the operator with `-from:`. `\u003CQUERY>` is `\"\u003CNAME>\" -from:\u003COPERATOR> since:\u003CFROM_DATE> until:\u003CTO_DATE>`, then ` OR \"\u003CDOMAIN>\"` added when the target has a domain and ` OR \"\u003CREPO>\"` added when it has a repo (leave each out when empty), all written in literally. One call per target:\n   ```bash\n   .\u002Fsecretcurl -s -o \u002Ftmp\u002Ftw-mr.json -w 'twitterapi http=%{http_code} bytes=%{size_download}\\n' --max-time 60 -G \"https:\u002F\u002Fapi.twitterapi.io\u002Ftwitter\u002Ftweet\u002Fadvanced_search\" \\\n     --data-urlencode 'query=\u003CQUERY>' --data-urlencode \"queryType=Latest\" \\\n     -H \"X-API-Key: {TWITTER_API_KEY}\"\n   ```\n   On `HTTP=200` with a non-empty `.tweets[]`, parse and mark `X_SOURCE=twitterapi`. Drop posts by `$OPERATOR` and the project's own accounts if any slipped through:\n   ```bash\n   jq -r '.tweets[] | [.id, .author.userName, .text, .url, .createdAt, .likeCount, .retweetCount, .replyCount] | @tsv' \u002Ftmp\u002Ftw-mr.json\n   ```\n   Engagement counts are exact; permalinks are `.url`. `createdAt` is Twitter-native (`Wed Sep 09 20:21:43 +0000 2026`); normalize with `strptime(\"%a %b %d %H:%M:%S %z %Y\")` before any date compare. advanced_search does **not** return `author.followers` - omit follower counts on this path (Path B can supply them).\n\n   **Path B - xAI Grok `x_search` (fallback).** Only if Path A returned non-2xx \u002F empty \u002F timeout, or `TWITTER_API_KEY` is unset. See the **Fetching** contract - set the Bash tool `timeout` to ≥180000, and capture the HTTP status. Use a unique tmp filename per target if you loop (e.g. `\u002Ftmp\u002Fxai-mr-\u003CSLUG>.json`). Build the body with the prompt inline and every value written into the jq filter literally (a `\"` inside a value becomes `\\\"`, and reword any `'`), and pipe it straight into the send:\n   ```bash\n   jq -n '{model:\"grok-4.7\", input:[{role:\"user\",content:\"Search X for posts by OTHER people mentioning the project \\\"\u003CNAME>\\\" (also its site \u003CDOMAIN> and repo \u003CREPO> when given), posted between \u003CFROM_DATE> and \u003CTO_DATE>. Exclude posts by the operator @\u003COPERATOR> and by the accounts of the project itself. For each mention return: @handle, the full post text, date, exact engagement counts (likes, retweets, replies; 0 if unknown), the approximate follower count of the poster if visible, and the direct link https:\u002F\u002Fx.com\u002Fhandle\u002Fstatus\u002FID. Prioritize people discovering it for the first time, asking confused questions, hitting friction (setup\u002Fdocs\u002Fmissing feature), comparing it to a competitor, or requesting a feature. Return a numbered list; if nobody is talking about it, say so explicitly.\"}], tools:[{type:\"x_search\",from_date:\"\u003CFROM_DATE>\",to_date:\"\u003CTO_DATE>\"}]}' \\\n     | .\u002Fsecretcurl -s -o \u002Ftmp\u002Fxai-mr.json -w '%{http_code}' --max-time 150 -X POST \"https:\u002F\u002Fapi.x.ai\u002Fv1\u002Fresponses\" \\\n     -H \"Content-Type: application\u002Fjson\" \\\n     -H \"Authorization: Bearer {XAI_API_KEY}\" \\\n     --data-binary @-\n   ```\n   On `HTTP=200` with a non-empty body, parse `\u002Ftmp\u002Fxai-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`.\n\n   **Path C - WebSearch (broader web + X last resort).** Always use WebSearch for the non-X surfaces - Reddit, Farcaster, personal blogs, newsletters, GitHub Discussions, HN, Product Hunt:\n   - Try both brand name and URL variants\n   - Time-box to last 7 days where the search engine supports it\n   - Skip results from the operator's own accounts and the project's own repos\n\n   WebSearch is **also** the last-resort fallback for X\u002FTwitter, but only when Paths A and B both truly failed (`key-unset`, `http-\u003Ccode>`, `empty`, or `timeout` - record the real reason per the **Fetching** contract, never \"XAI_API_KEY unavailable\" \u002F \"TWITTER_API_KEY unavailable\" when a key was set). On the X fallback query `site:x.com \"\u003Cproject name>\" after:${FROM_DATE}`; note in the log that X results came from WebSearch (lower quality) and set `X_SOURCE=websearch`.\n\n3. **Also check GitHub network signals** for each target with a known repo:\n   ```bash\n   gh api repos\u002FOWNER\u002FREPO --jq '{stars: .stargazers_count, forks: .forks_count, watchers: .watchers_count}'\n   ```\n   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.\n\n4. **Categorize each mention** found:\n   - **Discovery** — person found the project for the first time, sharing it, impressed (\"this is cool\", star notification, share)\n   - **Confusion** — person unclear on what it does, asking questions, mischaracterizing it\n   - **Friction** — person ran into a problem (setup, docs, missing feature)\n   - **Competitor comparison** — mentioned alongside or against a competing project\n   - **Feature request \u002F wish** — explicit ask for something missing\n   - **Press \u002F newsletter** — cited in a publication or digest\n\n5. **Identify engagement opportunities.** Flag any mention where:\n   - The person is confused and a 1-tweet clarification would help\n   - A feature request aligns with what's being built\n   - A competitor comparison is wrong or incomplete\n   - A high-follower account discovered the project (high-leverage reply opportunity)\n\n6. **Format the output** (under 4000 chars):\n   ```\n   *Mention Radar - ${today}*\n\n   {PROJECT NAME, uppercased}\n   - [source] - [what they said] - [category]\n   ...\n   (one section per target)\n\n   ENGAGEMENT OPPORTUNITIES\n   - [handle\u002Fsource]: [why worth replying]\n\n   QUIET: [project] - no external mentions found\n   ```\n   Use `QUIET: [project]` for any project with zero external mentions this cycle.\n   Skip GitHub-only star delta if it's less than 5 — only mention notable jumps.\n\n7. **Only notify if there's signal.** Skip notification if ALL projects are quiet and no GitHub deltas > 5 stars. Log `MENTION_RADAR_QUIET` instead.\n\n8. **Send via `.\u002Fnotify`** if there's anything worth surfacing.\n\n9. **Log to memory\u002Flogs\u002F${today}.md**:\n   ```\n   ### mention-radar\n   - **{project}:** [N mentions \u002F QUIET]\n   (one line per target)\n   - **Top find:** [best mention in one line, or \"none\"]\n   - **Engagement opps:** [N flagged, or 0]\n   - **Notification sent:** yes\u002Fno\n   ```\n\n## Guidelines\n\n- This is signal filtering, not a metrics report. One real conversation > ten impressions.\n- Prioritize quality of mention over quantity. A thoughtful Reddit post or HN comment matters more than a retweet.\n- Don't manufacture urgency. If there's nothing worth acting on, say so.\n- Be specific — link the source, quote the key line, name the person if identifiable.\n- The point is engagement opportunity and awareness, not vanity numbers.\n\n## Fetching\n\n`TWITTER_API_KEY` is **injected into your environment** for this skill (declared in `requires:`). **The primary fetch path for X\u002FTwitter mentions is a direct `curl` to `https:\u002F\u002Fapi.twitterapi.io\u002Ftwitter\u002Ftweet\u002Fadvanced_search` with header `X-API-Key: {TWITTER_API_KEY}`** (step 2, Path A). Grok `x_search` (`XAI_API_KEY`) is the fallback. There is no network sandbox blocking this. Just make the call.\n\n**You MUST attempt twitterapi.io before any X fallback.** The rules:\n\n1. **Check, don't assume.** Read the \"Keys set for this run\" line in your run notes, never a shell test (those are refused and cost a turn): `TWITTER_API_KEY` on that line = `KEY_PRESENT`, not on it = `KEY_UNSET`. If `KEY_PRESENT`, you are required to try Path A.\n2. **Capture the HTTP status** so the fallback decision is based on fact. Print `http=\u003Ccode>` before parsing. `HTTP=200` with a non-empty `.tweets[]` → use it (`X_SOURCE=twitterapi`). Put date windows **inside** the query with `since:YYYY-MM-DD until:YYYY-MM-DD`. `createdAt` is Twitter-native (`Wed Sep 09 20:21:43 +0000 2026`), not ISO - normalize with `strptime(\"%a %b %d %H:%M:%S %z %Y\")` before any date compare.\n3. **Path B - xAI Grok `x_search` (fallback).** Only when Path A fails (non-2xx \u002F empty \u002F timeout) or `TWITTER_API_KEY` is unset. Direct `curl` to `https:\u002F\u002Fapi.x.ai\u002Fv1\u002Fresponses` with `Authorization: Bearer {XAI_API_KEY}`. The `x_search` call typically takes 30-120s - **set the Bash tool `timeout` to at least 180000 (180s)** and keep **`--max-time 150`** on the curl. A slow curl is **not** a missing key. Build the payload with the `jq -n` filter shown in step 2 Path B (values written in literally) and pipe it straight into the send - a `>` redirect into a file is refused, and the `.\u002Fsecretcurl` command must stay 100% literal (no `$VAR`):\n   ```bash\n   jq -n '{...}' | .\u002Fsecretcurl -s -o \u002Ftmp\u002Fxai-mr.json -w '%{http_code}' --max-time 150 -X POST \"https:\u002F\u002Fapi.x.ai\u002Fv1\u002Fresponses\" \\\n     -H \"Content-Type: application\u002Fjson\" -H \"Authorization: Bearer {XAI_API_KEY}\" --data-binary @-\n   ```\n   It prints the status code (`HTTP`); `.\u002Fsecretcurl` also prints an `http=... bytes=...` line on stderr. Then parse `\u002Ftmp\u002Fxai-mr.json` with the standard `jq` extractor. `HTTP=200` with a non-empty body → use it (`X_SOURCE=api`).\n4. **Fall back only on a real failure**, and **record the true reason** - never write \"XAI_API_KEY unavailable\" \u002F \"TWITTER_API_KEY unavailable\" when a key was set. Use one of: `key-unset` (only if step 1 said `KEY_UNSET`), `http-\u003Ccode>` (non-2xx), `empty` (200 but no mentions parsed), `timeout` (curl exceeded `--max-time`).\n\n**WebSearch \u002F 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 a key works.\n\n## Environment Variables\n\n- `TWITTER_API_KEY` - twitterapi.io API key (sent as the `X-API-Key` header). Declared in `requires:`, so it is **injected into this skill's environment** and is the **primary** path for X\u002FTwitter mentions.\n- `XAI_API_KEY` - X.AI API key for Grok's `x_search` tool. Declared in `requires:` (optional `?`). The **fallback** path when `TWITTER_API_KEY` is unset or twitterapi returns non-2xx \u002F empty \u002F timeout. If both keys are unset, X mentions degrade to the WebSearch fallback at lower quality; the broader-web search is unaffected.\n- `gh` CLI — pre-authenticated in GitHub Actions; used for the GitHub network-signal check (step 3). Not an env var you set here.\n","> **${var}** — Comma-separated project names to track (e.g. \"MyApp, my-lib\"). If empty, derives targets from MEMORY.md and memory\u002Ftopics\u002Fprojects.md.\n\nRead memory\u002FMEMORY.md for current project status.\nRead the last 3 days of memory\u002Flogs\u002F to avoid re-surfacing already-noted mentions.\n\n## Steps\n\n1. **Define the targets.**\n   - If `${var}` is set: parse it as a comma-separated list of project names.\n   - Otherwise: scan `memory\u002FMEMORY.md` (goals, active topics) and `memory\u002Ftopics\u002Fprojects.md` (if it exists) for the operator's active projects. A target needs at least a name; collect a site\u002Fdomain and a GitHub `owner\u002Frepo` too when known.\n   - Cap at 6 targets — prefer the most active ones.\n   - If zero targets can be derived: log `MENTION_RADAR_SKIP: no projects configured — set var or add projects to memory\u002Ftopics\u002Fprojects.md` and stop. No notification.\n\n   For each target, build search terms:\n   - The exact project name in quotes (e.g. `\"MyApp\" site:x.com OR site:reddit.com OR site:news.ycombinator.com`)\n   - The domain if known (e.g. `\"myapp.xyz\"`)\n   - The repo if known (e.g. `site:github.com owner\u002Fmyapp`)\n\n2. **Search for external mentions.** X\u002FTwitter is fetched via **twitterapi.io** (**primary**); xAI Grok `x_search` is the fallback; 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\u002FSOUL.md` if present (call it `$OPERATOR`) so you can exclude their own posts.\n\n   **Shell shape.** Each Bash call is one allowed command (pipes are fine). The run refuses a call that sets a variable (`FROM_DATE=$(date ...)`, `Q=\"...\"`, `HTTP=$(.\u002Fsecretcurl ...)`), uses `if` \u002F `for` \u002F `while` or `[ -n ... ] &&` tests, or joins commands with `;`, `&&` or `||`, and each refusal costs a model turn. So get a date with a bare `date` call and write the printed value into later commands; write each target's name, domain, repo, the operator handle and the dates into each command literally (the `\u003CNAME>`, `\u003CFROM_DATE>` style placeholders in the snippets), jq filters included (a jq `$name` variable from `--arg` is refused, and so is a `>` redirect into a file, so the xAI body is piped straight into `.\u002Fsecretcurl ... --data-binary @-`); loop over targets by making one call per target; run one `jq` per call.\n\n   Get the window dates first, each `date` as its own Bash call:\n   ```bash\n   date -u -d '7 days ago' +%Y-%m-%d\n   ```\n   ```bash\n   date -u +%Y-%m-%d\n   ```\n   The first prints FROM_DATE, the second TO_DATE.\n\n   **Path A - twitterapi.io (primary, X\u002FTwitter mentions).** For each target, structured search for other people mentioning the project. See the **Fetching** contract below. Use a unique tmp filename per target if you loop (e.g. `\u002Ftmp\u002Ftw-mr-\u003CSLUG>.json`). `\u003CNAME>`\u002F`\u003CDOMAIN>`\u002F`\u003CREPO>` come from the target built in step 1, written in literally. Put the date window inside the query with `since:`\u002F`until:`; exclude the operator with `-from:`. `\u003CQUERY>` is `\"\u003CNAME>\" -from:\u003COPERATOR> since:\u003CFROM_DATE> until:\u003CTO_DATE>`, then ` OR \"\u003CDOMAIN>\"` added when the target has a domain and ` OR \"\u003CREPO>\"` added when it has a repo (leave each out when empty), all written in literally. One call per target:\n   ```bash\n   .\u002Fsecretcurl -s -o \u002Ftmp\u002Ftw-mr.json -w 'twitterapi http=%{http_code} bytes=%{size_download}\\n' --max-time 60 -G \"https:\u002F\u002Fapi.twitterapi.io\u002Ftwitter\u002Ftweet\u002Fadvanced_search\" \\\n     --data-urlencode 'query=\u003CQUERY>' --data-urlencode \"queryType=Latest\" \\\n     -H \"X-API-Key: {TWITTER_API_KEY}\"\n   ```\n   On `HTTP=200` with a non-empty `.tweets[]`, parse and mark `X_SOURCE=twitterapi`. Drop posts by `$OPERATOR` and the project's own accounts if any slipped through:\n   ```bash\n   jq -r '.tweets[] | [.id, .author.userName, .text, .url, .createdAt, .likeCount, .retweetCount, .replyCount] | @tsv' \u002Ftmp\u002Ftw-mr.json\n   ```\n   Engagement counts are exact; permalinks are `.url`. `createdAt` is Twitter-native (`Wed Sep 09 20:21:43 +0000 2026`); normalize with `strptime(\"%a %b %d %H:%M:%S %z %Y\")` before any date compare. advanced_search does **not** return `author.followers` - omit follower counts on this path (Path B can supply them).\n\n   **Path B - xAI Grok `x_search` (fallback).** Only if Path A returned non-2xx \u002F empty \u002F timeout, or `TWITTER_API_KEY` is unset. See the **Fetching** contract - set the Bash tool `timeout` to ≥180000, and capture the HTTP status. Use a unique tmp filename per target if you loop (e.g. `\u002Ftmp\u002Fxai-mr-\u003CSLUG>.json`). Build the body with the prompt inline and every value written into the jq filter literally (a `\"` inside a value becomes `\\\"`, and reword any `'`), and pipe it straight into the send:\n   ```bash\n   jq -n '{model:\"grok-4.7\", input:[{role:\"user\",content:\"Search X for posts by OTHER people mentioning the project \\\"\u003CNAME>\\\" (also its site \u003CDOMAIN> and repo \u003CREPO> when given), posted between \u003CFROM_DATE> and \u003CTO_DATE>. Exclude posts by the operator @\u003COPERATOR> and by the accounts of the project itself. For each mention return: @handle, the full post text, date, exact engagement counts (likes, retweets, replies; 0 if unknown), the approximate follower count of the poster if visible, and the direct link https:\u002F\u002Fx.com\u002Fhandle\u002Fstatus\u002FID. Prioritize people discovering it for the first time, asking confused questions, hitting friction (setup\u002Fdocs\u002Fmissing feature), comparing it to a competitor, or requesting a feature. Return a numbered list; if nobody is talking about it, say so explicitly.\"}], tools:[{type:\"x_search\",from_date:\"\u003CFROM_DATE>\",to_date:\"\u003CTO_DATE>\"}]}' \\\n     | .\u002Fsecretcurl -s -o \u002Ftmp\u002Fxai-mr.json -w '%{http_code}' --max-time 150 -X POST \"https:\u002F\u002Fapi.x.ai\u002Fv1\u002Fresponses\" \\\n     -H \"Content-Type: application\u002Fjson\" \\\n     -H \"Authorization: Bearer {XAI_API_KEY}\" \\\n     --data-binary @-\n   ```\n   On `HTTP=200` with a non-empty body, parse `\u002Ftmp\u002Fxai-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`.\n\n   **Path C - WebSearch (broader web + X last resort).** Always use WebSearch for the non-X surfaces - Reddit, Farcaster, personal blogs, newsletters, GitHub Discussions, HN, Product Hunt:\n   - Try both brand name and URL variants\n   - Time-box to last 7 days where the search engine supports it\n   - Skip results from the operator's own accounts and the project's own repos\n\n   WebSearch is **also** the last-resort fallback for X\u002FTwitter, but only when Paths A and B both truly failed (`key-unset`, `http-\u003Ccode>`, `empty`, or `timeout` - record the real reason per the **Fetching** contract, never \"XAI_API_KEY unavailable\" \u002F \"TWITTER_API_KEY unavailable\" when a key was set). On the X fallback query `site:x.com \"\u003Cproject name>\" after:${FROM_DATE}`; note in the log that X results came from WebSearch (lower quality) and set `X_SOURCE=websearch`.\n\n3. **Also check GitHub network signals** for each target with a known repo:\n   ```bash\n   gh api repos\u002FOWNER\u002FREPO --jq '{stars: .stargazers_count, forks: .forks_count, watchers: .watchers_count}'\n   ```\n   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.\n\n4. **Categorize each mention** found:\n   - **Discovery** — person found the project for the first time, sharing it, impressed (\"this is cool\", star notification, share)\n   - **Confusion** — person unclear on what it does, asking questions, mischaracterizing it\n   - **Friction** — person ran into a problem (setup, docs, missing feature)\n   - **Competitor comparison** — mentioned alongside or against a competing project\n   - **Feature request \u002F wish** — explicit ask for something missing\n   - **Press \u002F newsletter** — cited in a publication or digest\n\n5. **Identify engagement opportunities.** Flag any mention where:\n   - The person is confused and a 1-tweet clarification would help\n   - A feature request aligns with what's being built\n   - A competitor comparison is wrong or incomplete\n   - A high-follower account discovered the project (high-leverage reply opportunity)\n\n6. **Format the output** (under 4000 chars):\n   ```\n   *Mention Radar - ${today}*\n\n   {PROJECT NAME, uppercased}\n   - [source] - [what they said] - [category]\n   ...\n   (one section per target)\n\n   ENGAGEMENT OPPORTUNITIES\n   - [handle\u002Fsource]: [why worth replying]\n\n   QUIET: [project] - no external mentions found\n   ```\n   Use `QUIET: [project]` for any project with zero external mentions this cycle.\n   Skip GitHub-only star delta if it's less than 5 — only mention notable jumps.\n\n7. **Only notify if there's signal.** Skip notification if ALL projects are quiet and no GitHub deltas > 5 stars. Log `MENTION_RADAR_QUIET` instead.\n\n8. **Send via `.\u002Fnotify`** if there's anything worth surfacing.\n\n9. **Log to memory\u002Flogs\u002F${today}.md**:\n   ```\n   ### mention-radar\n   - **{project}:** [N mentions \u002F QUIET]\n   (one line per target)\n   - **Top find:** [best mention in one line, or \"none\"]\n   - **Engagement opps:** [N flagged, or 0]\n   - **Notification sent:** yes\u002Fno\n   ```\n\n## Guidelines\n\n- This is signal filtering, not a metrics report. One real conversation > ten impressions.\n- Prioritize quality of mention over quantity. A thoughtful Reddit post or HN comment matters more than a retweet.\n- Don't manufacture urgency. If there's nothing worth acting on, say so.\n- Be specific — link the source, quote the key line, name the person if identifiable.\n- The point is engagement opportunity and awareness, not vanity numbers.\n\n## Fetching\n\n`TWITTER_API_KEY` is **injected into your environment** for this skill (declared in `requires:`). **The primary fetch path for X\u002FTwitter mentions is a direct `curl` to `https:\u002F\u002Fapi.twitterapi.io\u002Ftwitter\u002Ftweet\u002Fadvanced_search` with header `X-API-Key: {TWITTER_API_KEY}`** (step 2, Path A). Grok `x_search` (`XAI_API_KEY`) is the fallback. There is no network sandbox blocking this. Just make the call.\n\n**You MUST attempt twitterapi.io before any X fallback.** The rules:\n\n1. **Check, don't assume.** Read the \"Keys set for this run\" line in your run notes, never a shell test (those are refused and cost a turn): `TWITTER_API_KEY` on that line = `KEY_PRESENT`, not on it = `KEY_UNSET`. If `KEY_PRESENT`, you are required to try Path A.\n2. **Capture the HTTP status** so the fallback decision is based on fact. Print `http=\u003Ccode>` before parsing. `HTTP=200` with a non-empty `.tweets[]` → use it (`X_SOURCE=twitterapi`). Put date windows **inside** the query with `since:YYYY-MM-DD until:YYYY-MM-DD`. `createdAt` is Twitter-native (`Wed Sep 09 20:21:43 +0000 2026`), not ISO - normalize with `strptime(\"%a %b %d %H:%M:%S %z %Y\")` before any date compare.\n3. **Path B - xAI Grok `x_search` (fallback).** Only when Path A fails (non-2xx \u002F empty \u002F timeout) or `TWITTER_API_KEY` is unset. Direct `curl` to `https:\u002F\u002Fapi.x.ai\u002Fv1\u002Fresponses` with `Authorization: Bearer {XAI_API_KEY}`. The `x_search` call typically takes 30-120s - **set the Bash tool `timeout` to at least 180000 (180s)** and keep **`--max-time 150`** on the curl. A slow curl is **not** a missing key. Build the payload with the `jq -n` filter shown in step 2 Path B (values written in literally) and pipe it straight into the send - a `>` redirect into a file is refused, and the `.\u002Fsecretcurl` command must stay 100% literal (no `$VAR`):\n   ```bash\n   jq -n '{...}' | .\u002Fsecretcurl -s -o \u002Ftmp\u002Fxai-mr.json -w '%{http_code}' --max-time 150 -X POST \"https:\u002F\u002Fapi.x.ai\u002Fv1\u002Fresponses\" \\\n     -H \"Content-Type: application\u002Fjson\" -H \"Authorization: Bearer {XAI_API_KEY}\" --data-binary @-\n   ```\n   It prints the status code (`HTTP`); `.\u002Fsecretcurl` also prints an `http=... bytes=...` line on stderr. Then parse `\u002Ftmp\u002Fxai-mr.json` with the standard `jq` extractor. `HTTP=200` with a non-empty body → use it (`X_SOURCE=api`).\n4. **Fall back only on a real failure**, and **record the true reason** - never write \"XAI_API_KEY unavailable\" \u002F \"TWITTER_API_KEY unavailable\" when a key was set. Use one of: `key-unset` (only if step 1 said `KEY_UNSET`), `http-\u003Ccode>` (non-2xx), `empty` (200 but no mentions parsed), `timeout` (curl exceeded `--max-time`).\n\n**WebSearch \u002F 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 a key works.\n\n## Environment Variables\n\n- `TWITTER_API_KEY` - twitterapi.io API key (sent as the `X-API-Key` header). Declared in `requires:`, so it is **injected into this skill's environment** and is the **primary** path for X\u002FTwitter mentions.\n- `XAI_API_KEY` - X.AI API key for Grok's `x_search` tool. Declared in `requires:` (optional `?`). The **fallback** path when `TWITTER_API_KEY` is unset or twitterapi returns non-2xx \u002F empty \u002F timeout. If both keys are unset, X mentions degrade to the WebSearch fallback at lower quality; the broader-web search is unaffected.\n- `gh` CLI — pre-authenticated in GitHub Actions; used for the GitHub network-signal check (step 3). Not an env var you set here.\n",{"name":5,"metadata":40,"description":7},{"var":41,"tags":42,"title":43,"commits":36,"category":25,"requires":44},"",[32,29],"Mention Radar",[45,46],"TWITTER_API_KEY","XAI_API_KEY?","main","9c042aa1b6d79fd49679637374e88c5874cc3aae","skills\u002Fmention-radar",2,"https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon","https:\u002F\u002Ft.me\u002Fmiroshark_aeon","https:\u002F\u002Fgithub.com\u002FMiroShark","https:\u002F\u002Fwww.miroshark.xyz\u002F","Simulate anything, for $1 & less than 10 min.","2026-11-13 00:17:51",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add MiroShark\u002Fmiroshark-aeon --skill mention-radar",{"tool":63,"command":64},"bunx","bunx skills add MiroShark\u002Fmiroshark-aeon --skill mention-radar",{"tool":66,"command":67},"pnpm","pnpm dlx skills add MiroShark\u002Fmiroshark-aeon --skill mention-radar","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fmention-radar\u002FSKILL.md",true,[],[72,108,128,155,179,201],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":88,"publishedAt":35},"01M6J4P8XKB8RJ7PCYMZPZ0F6S","you-web-search","Web search using You.com Search API with high-quality, cited results — runs keyless out of the box; YDC_API_KEY unlocks higher limits and real-time web crawling","https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fyou-web-search\u002FSKILL.md",[78,83],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[89,90,91,92,24,93,94,26,95,96,97,98,99,100,101,102,103,104,105,106,107],"web search","search","you","you web search","time","only","web crawling","read","read-only","real-time","basics","keyless","with","research","results","high","quality","box","limits",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":114,"publishedAt":35},"01M6J4P4H35WQG6RHGTTACSMVW","write-tweet","Multi-format tweet studio - standalone drafts (10 across 5 size tiers), a 5-10 tweet thread, or 10 remixes of past tweets, selected via ${var}","https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fwrite-tweet\u002FSKILL.md",[],[115,116,117,32,118,26,119,22,120,121,99,31,122,123,124,125,126,127],"write","write tweet","standalone","studio","across","past","drafts","thread","multi","size","via","format","content",{"skillNo":129,"name":130,"nameZh":6,"description":131,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":137,"publishedAt":35},"01M6J4P11K7ZJ2PJDHDTTFZ1HY","weekly-aeoncard","Build a weekly token-consumption recap image from memory\u002Ftoken-usage.csv - this week + all-time totals, top skills, rendered as a shareable SVG card.","https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fweekly-aeoncard\u002FSKILL.md",[134],{"categoryNo":135,"categoryName":136,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000016","图像与多媒体",[138,139,140,141,142,143,144,93,145,146,147,148,149,150,25,151,152,115,153,154],"weekly","weekly aeoncard","as","usage","SVG","memory","card","Meta","image","recap","csv","monitoring","notifications","top","build","token","aeon",{"skillNo":156,"name":157,"nameZh":6,"description":158,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":159,"categories":160,"keywords":161,"publishedAt":35},"01M6J4NVJYQP5DNKSGXAXQW06B","vuln-tracker","One lifecycle poll over everything vuln-scanner produces - PR and advisory status, PVR triage transitions, and pending-disclosure aging, with a stars-secured impact headline and one action queue.","https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fvuln-tracker\u002FSKILL.md",[],[162,163,145,164,165,115,153,166,167,168,169,170,171,29,172,173,174,101,175,176,177,178],"tracker","vuln tracker","impact","scanner","status","action","security","pr","stars","lifecycle","gh","aging","advisory","github","transitions","triage","global",{"skillNo":180,"name":181,"nameZh":6,"description":182,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":183,"categories":184,"keywords":188,"publishedAt":35},"01M6J4NNQCHTKNGENAPJQ8KYHR","vuln-scanner","Audit trending repos for real security vulnerabilities and disclose responsibly - scan and route findings (PVR \u002F dependency PR), re-submit queued advisories, and send armed email disclosures","https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fvuln-scanner\u002FSKILL.md",[185],{"categoryNo":186,"categoryName":187,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000005","邮件与沟通",[165,189,190,33,191,145,192,168,193,194,195,29,175,196,178,197,26,198,199,200],"vuln scanner","resend","trending","repos","email","for","scan","vulnerabilities","submit","route","audit","send",{"skillNo":202,"name":203,"nameZh":6,"description":204,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":205,"categories":206,"keywords":208,"publishedAt":35},"01M6J4NFBXTGG0R4M484T0KNYW","video-script","Turn a repo, product page, or update into a recording-ready video script in a receipts-first format - verifies every claim against live sources, then writes timestamped VO + on-screen direction with a plain-language glossary, assets checklist, anti-tells, and a verify-before-recording list","https:\u002F\u002Fgithub.com\u002FMiroShark\u002Fmiroshark-aeon\u002Fblob\u002Fmain\u002Fskills\u002Fvideo-script\u002FSKILL.md",[207],{"categoryNo":135,"categoryName":136,"taxonomyType":81,"taxonomyTypeDesc":82},[209,210,211,212,213,214,215,216,217,99,218,219,220,101,221,222,223,224,225,126,226,227,228],"Video","video script","script","recording","sources","ready","direction","page","repo","claim","plain-language","glossary","first","verify","product","screen","update","list","live","receipts"]