| tools | [{"name":"FetchHackerNews","description":"Fetch the 30 current top HN stories. Returns JSON array of {id, title, url, score, by, descendants, hn_url, age_hours}. Used by discover-customers, monitor-mentions. Filter results by goal-relevant keywords and brief topics in your reasoning; score 0-1 for technical specificity.","cmd":"$SKILL_DIR/scripts/sites/hackernews.sh","tier":"read","timeout_ms":30000},{"name":"FetchHNSearch","description":"Keyword-search Hacker News for RECENT story threads on a topic, via the public Algolia HN API (no auth). The discovery counterpart to FetchHackerNews — finds threads worth COMMENTING on so a young HN account builds karma before posting. Args: \"<query>\" [days=7]; with no query, OR-joins sites.hackernews.keywords. Returns JSON array of {id, title, url, hn_url, points, num_comments, author, text, created_iso, age_hours}. Prefer hits with num_comments > 0 and low age_hours (active threads). Gated on sites.hackernews.enabled.","cmd":"$SKILL_DIR/scripts/sites/hn-search.sh {{query}} {{days}}","tier":"read","timeout_ms":30000},{"name":"FetchHNThread","description":"Pull one HN thread's OP + comment tree via the public Algolia API (no auth). Used by discover-customers to read the OP + real discussion for GROUNDING a top-level reply to the post (so the draft answers the actual question and doesn't repeat existing comments). Arg: an HN item id or news.ycombinator.com/item?id=… url. Returns { thread_url, thread_title, op:{author,body,url, age_hours}, comments:[{author,body,url,age_hours}] (cap 25), errors } — same shape as FetchRedditThread.","cmd":"$SKILL_DIR/scripts/sites/hn-thread.sh {{thread}}","tier":"read","timeout_ms":30000},{"name":"FetchHNSubmitCandidates","description":"Find GOOD third-party ARTICLES to SUBMIT to HN — the way to lower a young account's \"own-post ratio\" so its own Show HN stops getting auto-killed. (HN's software filters accounts that submit mostly their own links; an HN mod's fix: intersperse interesting posts from OTHER sources. Comments build karma but do NOT move the submission ratio — only third-party submissions do.) Reads curated HN-taste sources — lobste.rs front page + quality tech subreddits (sites.hackernews.submit_sources) — then DEDUPS each URL against HN via the public Algolia API and DROPS anything already submitted (reposts get killed). Arg: [max=5] (default 5 — HN tolerates only a couple of your own submissions per day, so a short list is plenty). Returns JSON array of {title, url, source, score, age_hours, comments_url, hn_status}, best/freshest first; hn_status \"fresh\" = not on HN, \"unchecked\" = Algolia unreachable (verify before posting). These are SUBMIT-this- link items (a title+url to paste into HN's submit form) — NOT threads to comment on, and NEVER the user's own work. Gated on sites.hackernews.enabled.","cmd":"$SKILL_DIR/scripts/sites/hn-submit-finder.sh {{max}}","tier":"read","timeout_ms":45000},{"name":"FetchHNMentions","description":"The HN inbox signal HN never sends: comments on YOUR submissions (HN's \"threads\" page only shows replies to your comments — a comment on your story is invisible unless you revisit the item page). Via public Algolia, no auth. Returns reply_to_me (new comments on your recent stories + replies to your recent comments, with your text as parent_comment_body) and mention (your username written in a comment) — same shape as FetchRedditMentions: {username, items: [{kind, title, body, url, author, created_iso, story_url, parent_comment_body?}], count, errors}. Arg: [hours=336] look-back. Needs sites.hackernews.username (Settings); gated on sites.hackernews.enabled.","cmd":"$SKILL_DIR/scripts/sites/hn-mentions.sh {{hours}}","tier":"read","timeout_ms":45000},{"name":"FetchReddit","description":"Fetch the 25 newest threads from each subreddit listed in ~/.linggen/skills/pulse/config.json (sites.reddit.subs). Returns JSON array of {sub, title, url, author, comments, age_hours, summary} (author is the OP handle, u/<name>). Used by discover-customers and monitor-mentions. Reads Reddit's PUBLIC `.rss` feeds (Reddit closed the anonymous `.json` API in Nov 2025, but `/r/<sub>/new.rss` still works with no auth). `comments`/`score` are 0 (RSS omits them) — score by title/summary relevance. A sub that hits the anon rate limit serves its last-good cached feed instead (items get `stale: true`, age_hours recomputed) — treat stale items normally, just expect some may already be a scan old.","cmd":"$SKILL_DIR/scripts/sites/reddit.sh","tier":"read","timeout_ms":90000},{"name":"FetchRedditThread","description":"Pull ONE Reddit thread's OP + comments via the public `.rss` feed (no auth; Reddit closed .json Nov 2025). Pass the thread URL or bare post id. Returns {thread_url, thread_title, op:{author, body, url, age_hours}, comments:[{author, body, url, age_hours}] (cap 25), errors}. Used by discover-customers to read the real discussion before drafting a comment-starter — far better than guessing from the thread title alone.","cmd":"$SKILL_DIR/scripts/sites/reddit-thread.sh {{thread}}","tier":"read","timeout_ms":20000,"args":{"thread":{"type":"string","required":true,"description":"Reddit thread URL (.../comments/<id>/...) or bare post id."}}},{"name":"FetchRedditMentions","description":"Reddit mention/reply monitoring via RSS (Reddit closed the .json API Nov 2025; .rss still works). With a `private_rss_feed_token` in config (Settings → Reddit), reads the user's PRIVATE inbox feeds — `reply_to_me` (direct replies to the user's comments/posts) and `mention` items — the real \"someone replied to me\" signal, no OAuth/app. Without a token, falls back to PUBLIC search RSS for u/<username> mentions only (no replies). Returns {items:[{kind, title, body, url, author, sub, created_iso, score, num_comments, watched_term, parent_comment_body?, parent_comment_url?}], count, errors}. Because the data is RSS, score/num_comments are 0 (rank by relevance, not heat). For `reply_to_me` items the script pre-walks the thread and attaches the user's own comment as `parent_comment_body` (+ `parent_comment_url`), so a card can show both sides. **kind ∈ reply_to_me | mention | own_comment.** The `own_comment` rows are PAGE-SIDE FILTER PLUMBING only — they carry just {kind, title, url, created_iso} and feed pulse-app.js's already-commented dedup. NEVER turn an `own_comment` row into a card; the agent ignores them entirely. Rate limit ~10 req/min; script makes up to ~8 calls per invocation. DMs/inbox are unavailable (Reddit gates Data API OAuth behind manual approval).","cmd":"$SKILL_DIR/scripts/sites/reddit-mentions.sh","tier":"read","timeout_ms":30000},{"name":"FetchX","description":"Search recent X (Twitter) posts for a topic — a discovery supplement. Reads the user's logged-in x.com session through the linggen-browser extension (bridge op \"search\") — no paid API, $0/read. Gated OFF by default; set sites.x.keyword_search=true to enable. Pass a topic query; excludes retweets/replies, English only. Returns a JSON array of {source:\"x\", author, handle, followers, title, text, url, score, likes, reposts, replies, created_iso, age_hours} (title == text, so score it like a Reddit thread). [] when the bridge/extension is unavailable — cap to the top few topics regardless.","cmd":"$SKILL_DIR/scripts/sites/x-search.sh {{query}}","tier":"read","timeout_ms":25000,"args":{"query":{"type":"string","required":true,"description":"Topic/keyword to search recent X posts for."}}},{"name":"FetchXTargets","description":"The X GROWTH engine — the PRIMARY X discovery source. Pulls the FRESHEST original posts from the target ROSTER (the curated accounts in sites.x.roster, plus any sites.x.target_accounts pins), read from the logged-in x.com session via the linggen-browser extension (bridge op \"targets\", $0/read), so the user can reply EARLY while the post is gaining traction and the reply slot is still visible. Replying under accounts whose audience IS the target user is the real follower-growth lever — far better than keyword search (FetchX). Same output shape as FetchX, newest-first. Pass an optional space/comma-separated handle list to fetch a SPECIFIC subset (used for progressive per-source refresh); with no arg it pulls the whole roster. [] when the roster is empty or the bridge/extension is unavailable. Prefer hits with low age_hours.","cmd":"$SKILL_DIR/scripts/sites/x-targets.sh {{handles}}","tier":"read","timeout_ms":25000,"args":{"handles":{"type":"string","required":false,"description":"Optional subset of handles to pull (space/comma-separated); omit for the whole roster."}}},{"name":"FetchXWhoToFollow","description":"X's own \"Who to follow\" recommendations, read from the logged-in x.com session via the linggen-browser extension (bridge op \"whotofollow\", $0/read). SOURCE 1 (highest priority) for building the target roster: X personalizes these from the user's graph and already excludes people the user follows, so every result is a genuine not-yet-followed candidate. Already excludes the current roster, ignored accounts, and dismissed suggestions. Returns a JSON array of {handle, name, followers, following_count, bio, verified}. [] when the bridge/extension is unavailable. Pass an optional max (default 60, cap 100).","cmd":"$SKILL_DIR/scripts/sites/x-whotofollow.sh {{max}}","tier":"read","timeout_ms":30000,"args":{"max":{"type":"string","required":false,"description":"Max candidates to return (default 60, 1–100)."}}},{"name":"FetchXFollowing","description":"Lists the accounts a handle follows, read from the logged-in x.com session via the linggen-browser extension (bridge op \"following\", $0/read), cached 24h. TWO uses in roster building: (no arg) → the USER's OWN following — the pool to tag which roster accounts are already-followed, and a candidate source of niche accounts the user already vetted; (handle arg) → that handle's following, the SOURCE 3 \"second-degree\" signal (accounts your target accounts follow → central niche accounts worth surfacing). Returns a JSON array of {handle, name, followers, following_count, bio, verified}. [] when the bridge/extension is unavailable. Pass an optional handle, then an optional max.","cmd":"$SKILL_DIR/scripts/sites/x-following.sh {{handle}} {{max}}","tier":"read","timeout_ms":30000,"args":{"handle":{"type":"string","required":false,"description":"Whose following to read; omit for the user's own."},"max":{"type":"string","required":false,"description":"Max accounts to return (default 400, cap 1000)."}}},{"name":"FetchXMentions","description":"X (Twitter) mention/reply monitoring, read from the user's logged-in x.com session via the linggen-browser extension (bridge op \"mentions\", $0/read). Surfaces recent mentions and replies to the user's tweets; for replies it resolves the tweet you replied-to and, when that parent is YOUR tweet, attaches it as parent_comment_body (so the card shows your tweet + their reply + a draft, same shape as FetchRedditMentions). Returns {items:[{kind, title, body, url, author, created_iso, score, watched_term, parent_comment_body?, parent_comment_url?}], count, errors}; kind ∈ reply_to_me | mention. Empty + error until the extension ships the \"mentions\" reader op (returns module_unavailable today).","cmd":"$SKILL_DIR/scripts/sites/x-mentions.sh","tier":"read","timeout_ms":30000},{"name":"FetchXOwnPosts","description":"The user's OWN recent X (Twitter) posts with engagement metrics (likes, reposts, replies, impressions), read from the logged-in x.com session via the linggen-browser extension (bridge op \"own\", $0/read). Pass an optional max count (default 10). Returns {username, items:[{text, url, likes, reposts, replies, views, score, created_iso, age_hours}], replied_to:[\"<x.com status url>\", …], count, errors}; score = likes + reposts. `items` is original posts only (replies/retweets excluded) — used by draft-content for the x-post lane so a new post builds on what the user already shipped instead of repeating it, and so high-engagement past posts inform what themes to write more of (the performance feedback loop). `replied_to` is the parent tweets the user has already replied to — Pulse uses it to suppress already-engaged posts from discovery (same rule as Reddit's already-commented filter). Reads x.com/<handle>/with_replies via the extension; empty + error only when the bridge/extension is unavailable.","cmd":"$SKILL_DIR/scripts/sites/x-own.sh {{max}}","tier":"read","timeout_ms":30000,"args":{"max":{"type":"string","required":false,"description":"Max number of own posts to fetch (default 10, 5–100)."}}},{"name":"FetchBlueskyMentions","description":"Public AT Proto monitoring for Bluesky — no auth required. Reads sites.bluesky.handle from config, then surfaces (a) recent posts that mention @<handle>, (b) the user's own recent top-level posts, (c) the user's own recent replies on others' threads, (d) direct replies to the user's recent posts (walked from getPostThread depth=1, since Bluesky's public API has no inbox / unified notifications without auth). Returns same shape as FetchRedditMentions: {items: [{kind, title, body, url, author, sub, created_iso, score, num_comments, watched_term}], count, errors}. kind ∈ mention | reply_to_me | own_post | own_reply. Generous rate limit (~3000/5min) but script caps at ~8 calls per invocation. sub is always \"bsky\".","cmd":"$SKILL_DIR/scripts/sites/bluesky-mentions.sh","tier":"read","timeout_ms":30000},{"name":"FetchBlueskyKeywords","description":"Search Bluesky public posts for the category keywords listed in sites.bluesky.keywords (e.g. [\"local LLM\", \"Apple Silicon AI\", \"agent runtime\"] — category phrases extracted from the brief, NOT brand names). Returns a JSON array of {source, watched_term, title, url, author, author_display, body, summary, created_iso, age_hours, reply_count, repost_count, like_count}. Used by discover-customers (Bluesky has no stable communities like subreddits, so keyword search is the discovery primary). Dedupes across keywords by post URL.","cmd":"$SKILL_DIR/scripts/sites/bluesky-search.sh","tier":"read","timeout_ms":30000},{"name":"FetchLobsters","description":"Fetch the lobste.rs newest feed. Returns JSON array of {title, url, comments_url, score, tags, submitter_user, created_at, description}. Used by discover-customers.","cmd":"$SKILL_DIR/scripts/sites/lobsters.sh","tier":"read","timeout_ms":30000},{"name":"FetchArxiv","description":"Fetch the 30 most recently submitted arxiv papers from CS.AI / CS.LG / CS.CL. Returns JSON array of {title, summary, url, authors, published}. Used by discover-customers when goals are research-adjacent.","cmd":"$SKILL_DIR/scripts/sites/arxiv.sh","tier":"read","timeout_ms":30000},{"name":"FetchRSS","description":"Fetch each RSS/Atom feed listed in ~/.linggen/skills/pulse/config.json (sites.rss.feeds). Returns JSON array of {feed, title, url, summary, date}. Used by discover-customers when RSS feeds are configured.","cmd":"$SKILL_DIR/scripts/sites/rss.sh","tier":"read","timeout_ms":30000},{"name":"FetchProductHuntRSS","description":"Fetch today's launches from Product Hunt's public RSS feed. Returns JSON array of {title, url, summary, date, author, source}. Used by discover-customers — competing launches surface here.","cmd":"$SKILL_DIR/scripts/sites/product-hunt.sh","tier":"read","timeout_ms":20000}] |