From 5491e44459202360d67a9e1ba2aa156cc7999509 Mon Sep 17 00:00:00 2001 From: Fariz Anjum Date: Fri, 29 May 2026 20:05:43 +0530 Subject: [PATCH 1/4] feat(skill): add company-radar and sync README counters --- README.md | 15 +- packages/cli/registry.json | 12 + scripts/update-readme.ts | 10 +- skills/company-radar/README.md | 162 +++++++ skills/company-radar/SKILL.md | 410 ++++++++++++++++++ .../references/company-profile-format.md | 151 +++++++ .../references/heat-score-methodology.md | 116 +++++ .../references/radar-report-template.md | 187 ++++++++ .../references/skill-integration-map.md | 280 ++++++++++++ .../company-radar/scripts/heat-score-calc.mjs | 140 ++++++ 10 files changed, 1477 insertions(+), 6 deletions(-) create mode 100644 skills/company-radar/README.md create mode 100644 skills/company-radar/SKILL.md create mode 100644 skills/company-radar/references/company-profile-format.md create mode 100644 skills/company-radar/references/heat-score-methodology.md create mode 100644 skills/company-radar/references/radar-report-template.md create mode 100644 skills/company-radar/references/skill-integration-map.md create mode 100644 skills/company-radar/scripts/heat-score-calc.mjs diff --git a/README.md b/README.md index 7d567c0..93f7847 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@
- Typing SVG + Typing SVG

@@ -13,7 +13,7 @@
[![npm version](https://img.shields.io/npm/v/@opendirectory.dev/skills.svg?style=flat-square)](https://www.npmjs.com/package/@opendirectory.dev/skills) -[![Skills](https://img.shields.io/badge/skills-58-blue.svg?style=flat-square)](skills/) +[![Skills](https://img.shields.io/badge/skills-59-blue.svg?style=flat-square)](skills/) [![Stars](https://img.shields.io/github/stars/Varnan-Tech/opendirectory?style=flat-square&color=yellow)](https://github.com/Varnan-Tech/opendirectory/stargazers) [![Contributors](https://img.shields.io/github/contributors/Varnan-Tech/opendirectory?style=flat-square&color=orange)](https://github.com/Varnan-Tech/opendirectory/graphs/contributors) [![Agents](https://img.shields.io/badge/agents-7-blueviolet.svg?style=flat-square)](#quick-start) @@ -40,7 +40,7 @@ Or list all skills: ```bash npx "@opendirectory.dev/skills" list ``` -*56 specialized skills across GTM, growth, and developer tooling* +*59 specialized skills across GTM, growth, and developer tooling* ### 2. Pick your agent ```bash @@ -230,11 +230,11 @@ Run these commands inside Claude Code: ## All Skills -58 skills across GTM, growth automation, technical marketing, and developer tooling. +59 skills across GTM, growth automation, technical marketing, and developer tooling. -58 skills across 8 categories — click to expand +59 skills across 8 categories — click to expand
@@ -376,6 +376,11 @@ Run these commands inside Claude Code: + + + + + diff --git a/packages/cli/registry.json b/packages/cli/registry.json index c8726fa..29985c1 100644 --- a/packages/cli/registry.json +++ b/packages/cli/registry.json @@ -49,6 +49,18 @@ "version": "0.0.1", "path": "skills/cold-email-verifier" }, + { + "name": "company-radar", + "description": "Competitive intelligence orchestrator tracking companies across 8+ platforms (GitHub, Twitter, Reddit, HN, PH, YC Jobs) with heat scores and AI bri...", + "tags": [ + "Social Media", + "AI", + "Developer Tools" + ], + "author": "OpenDirectory", + "version": "1.0.0", + "path": "skills/company-radar" + }, { "name": "competitor-pr-finder", "description": "Give it your product URL or description.", diff --git a/scripts/update-readme.ts b/scripts/update-readme.ts index e85f108..66ede3c 100644 --- a/scripts/update-readme.ts +++ b/scripts/update-readme.ts @@ -56,7 +56,7 @@ function detectCategoryFromContent(name: string, description: string): string { if (/^(vid-|graphic-|blog-cover-image)/.test(n)) return 'Visual & Media'; if (/^(email-newsletter|cook-the-blog|noise2blog|human-tone|linkedin-post|tweet-thread|noise-to-linkedin|newsletter)/.test(n)) return 'Content'; if (/^(producthunt|show-hn|oss-launch|brand-alchemy|product-update-logger)/.test(n)) return 'Launch'; - if (/^(hackernews|reddit-icp|reddit-post|npm-downloads|yc-intent|twitter-gtm|sdk-adoption|gh-issue|map-your-market|competitor-pr|google-trends|meta-ads|meta-tribe)/.test(n)) return 'GTM Intelligence'; + if (/^(hackernews|reddit-icp|reddit-post|npm-downloads|yc-intent|twitter-gtm|sdk-adoption|gh-issue|map-your-market|competitor-pr|google-trends|meta-ads|meta-tribe|company-radar)/.test(n)) return 'GTM Intelligence'; if (/^(outreach-sequence|cold-email)/.test(n)) return 'Outreach'; if (/^(pricing-|position-me|meeting-brief|linkedin-job-post|where-your-customer|vc-)/.test(n)) return 'Research'; if (/^(kill-the-standup|dependency-update|docs-from-code|pr-description|explain-this-pr|claude-md|llms-txt|schema-markup)/.test(n)) return 'Developer Tools'; @@ -266,6 +266,14 @@ function updateReadme() { /\d+ skills across GTM/, `${skills.length} skills across GTM` ); + updatedContent = updatedContent.replace( + /lines=\d+\+Agent\+Skills/, + `lines=${skills.length}+Agent+Skills` + ); + updatedContent = updatedContent.replace( + /\d+ specialized skills across GTM/, + `${skills.length} specialized skills across GTM` + ); fs.writeFileSync(README_PATH, updatedContent, 'utf-8'); diff --git a/skills/company-radar/README.md b/skills/company-radar/README.md new file mode 100644 index 0000000..2bc8979 --- /dev/null +++ b/skills/company-radar/README.md @@ -0,0 +1,162 @@ +# Company Radar + +Competitive intelligence orchestrator for opendirectory. Takes company names, researches them across 8+ platforms in parallel, computes a 0-100 heat score, and outputs structured radar reports with AI briefings. + +--- + +## Install + +```bash +npx "@opendirectory.dev/skills" install company-radar --target claude +``` + +### Video Tutorial +Watch this quick video to see how it's done: + +https://github.com/user-attachments/assets/ee98a1b5-ebc4-452f-bbfb-c434f2935067 + +### Step 1: Download the skill from GitHub +1. Copy the URL of this specific skill folder from your browser's address bar. +2. Go to [download-directory.github.io](https://download-directory.github.io/). +3. Paste the URL and click **Enter** to download. + +### Step 2: Install the Skill in Claude +1. Open your **Claude desktop app**. +2. Go to the sidebar on the left side and click on the **Customize** section. +3. Click on the **Skills** tab, then click on the **+** (plus) icon button to create a new skill. +4. Choose the option to **Upload a skill**, and drag and drop the `.zip` file (or you can extract it and drop the folder, both work). + +> **Note:** For some skills (like `position-me`), the `SKILL.md` file might be located inside a subfolder. Always make sure you are uploading the specific folder that contains the `SKILL.md` file! + + +## What It Does + +Given a list of companies to track, Company Radar: + +1. **Builds a profile** for each company (domain, social handles, founders, YC batch) +2. **Scans 8 channels in parallel** — GitHub, Twitter/X, Reddit, Hacker News, Product Hunt, YC Jobs, Web/Press, Pricing +3. **Computes a heat score** (0-100) across 4 dimensions: Authority, Shipping, Social, Growth +4. **Generates an AI executive briefing** per company and a landscape-level summary +5. **Outputs a structured radar report** with leaderboard, deep dives, and alerts + +--- + +## Files + +| File | Purpose | +|---|---| +| `SKILL.md` | Main orchestration skill — entry point for the AI agent | +| `README.md` | Install and usage docs | +| `scripts/heat-score-calc.mjs` | Standalone heat score engine — run on collected signal data | +| `references/heat-score-methodology.md` | Full scoring formulas and examples | +| `references/radar-report-template.md` | Report output structure | +| `references/company-profile-format.md` | Company data schema | +| `references/skill-integration-map.md` | How to call each opendirectory skill for channel data | + +--- + +## Prerequisites + +- **opencode** with the opendirectory skill set installed +- The following skills available in your opendirectory config: + - `reddit-icp-monitor` (optional; falls back to Tavily) + - `twitter-GTM-find-skill` (optional; falls back to Tavily) + - `hackernews-intel` (optional; falls back to HN Algolia) + - `yc-jobs-scraper` (required for YC job signals) + - `producthunt-launch-kit` (optional; falls back to Tavily) + - `competitor-pr-finder` (optional) + - `map-your-market` (optional, for landscape analysis) +- **Tavily API key** (for web search fallbacks) +- **GitHub CLI** (`gh`) installed and authenticated (for GitHub signal collection) + +--- + +## Usage + +### Basic Radar Run + +```text +/company-radar + +Companies to track: Vercel, Netlify, Railway +``` + +The skill walks through all steps: Parse input → Build profiles → Collect signals (parallel) → Heat score via `scripts/heat-score-calc.mjs` → Generate briefing → Assemble report + +### Using the Heat Score Script Directly + +After collecting signal data, you can run the scorer standalone: + +```bash +# From the skill directory +node scripts/heat-score-calc.mjs --file signals.json + +# Or pipe raw JSON +cat signals.json | node scripts/heat-score-calc.mjs +``` + +Input is a JSON file with `companies[]` containing signal data. Output is scored JSON with per-dimension breakdowns and auto-generated alerts. + +### Quick Heat Score Only + +```text +/company-radar + +Companies to track: Supabase +Mode: heat-score-only +``` + +Returns just the heat score with minimal context -- no full report. + +### Recurring Radar + +```text +/company-radar + +Companies: Vercel, Netlify, Railway, Supabase +Schedule: daily +``` + +Runs the radar and compares scores with the previous run to show deltas. + +--- + +## Output + +The skill produces a single structured markdown report containing: + +- **Executive Summary** -- landscape-level synthesis, ranked rankings, key alerts +- **Heat Score Leaderboard** -- table of all tracked companies sorted by score +- **Per-Company Deep Dives** -- full signal detail per channel, heat score breakdown, AI executive briefing +- **Alerts Summary** -- notable signals grouped by severity +- **Data Quality Notes** -- which channels returned data per company + +--- + +## Heat Score Dimensions + +| Dimension | Max | Measures | +|---|---|---| +| Authority | 25 | GitHub stars/forks, Product Hunt validation | +| Shipping | 25 | Commit velocity, release frequency, recency | +| Social | 25 | Twitter, Reddit, HN, YouTube activity | +| Growth | 25 | Hiring volume, sentiment, traction indicators | + +Total: **0-100** + +Activity levels: **High** (60+), **Medium** (30-59), **Low** (1-29), **Dormant** (0) + +--- + +## Customization + +### Add a New Channel + +1. Add the signal formulas to `references/heat-score-methodology.md` +2. Add the skill mapping to `references/skill-integration-map.md` +3. Add the data fields to the report template in `references/radar-report-template.md` +4. Update the orchestration flow in `SKILL.md` Step 4 + +### Adjust Scoring Weights + +Edit the formula tables in `SKILL.md` Steps 5-8 and `references/heat-score-methodology.md`. Each dimension caps at 25 points max. diff --git a/skills/company-radar/SKILL.md b/skills/company-radar/SKILL.md new file mode 100644 index 0000000..1f63f01 --- /dev/null +++ b/skills/company-radar/SKILL.md @@ -0,0 +1,410 @@ +--- +name: company-radar +description: Competitive intelligence orchestrator tracking companies across 8+ platforms (GitHub, Twitter, Reddit, HN, PH, YC Jobs) with heat scores and AI briefings. +compatibility: [claude-code, gemini-cli, github-copilot] +author: OpenDirectory +version: 1.0.0 +--- + +# Company Radar + +**Competitive intelligence orchestrator.** Takes company names, runs parallel research across 8+ platforms, scores each on a 0-100 heat scale, and produces a structured radar report with AI briefings. + +This is an orchestration skill. It delegates data collection to existing opendirectory micro-skills and coordinates their output --- it doesn't replace them. + +--- + +## Architecture + +``` +INPUT: Company name(s) / URL(s) + | + [1. Profile Phase] -- Web research to build company profiles + | + [2. Signal Collection] -- Parallel platform research (8 channels) + / | | | | | \ \ + GH TW RD HN PH YC WEB MEDIA + | + [3. Scoring Engine] -- 4-dimension heat score (0-100) + | + [4. AI Synthesis] -- Executive briefing generation + | +OUTPUT: Radar Report + Per-Company Deep Dives +``` + +### Signal Channels and Their Opendirectory Mappings + +| Channel | Opendirectory Skill | What It Detects | +|---|---|---| +| GitHub | `gh-issue-to-demand-signal` + web search | Stars, forks, commits, releases, shipping velocity | +| Twitter/X | `twitter-GTM-find-skill` | Tweets, mentions, engagement, founder activity | +| Reddit | `reddit-icp-monitor`, `reddit-post-engine` | Community sentiment, pain points, buzz | +| Hacker News | `hackernews-intel` | Story mentions, points, front-page signals | +| Product Hunt | `producthunt-launch-kit` | Launches, votes, maker activity | +| YC Jobs | `yc-intent-radar-skill` / `yc-jobs-scraper` | Job listings, hiring departments, growth signals | +| Web / Press | Tavily search + `competitor-pr-finder` | News, product announcements, funding | +| Pricing | `pricing-finder` | Pricing changes, tier updates, plan structure | +| Market Position | `map-your-market` | ICP, competitor landscape, messaging gaps | + +--- + +## Common Mistakes + +| The agent will want to... | Why that's wrong | +|---|---| +| Run skills sequentially | All 8 signal channels are independent. Must run in parallel. | +| Hallucinate GitHub star counts or hiring numbers | Every data point must trace to a specific search result or skill output. No "approx 500 stars". | +| Skip the heat score computation | The radar report requires scored output, not just raw data dump. Heat score is the core differentiator. | +| Output incomplete reports because a skill failed | One failing channel does not block the full report. Score what you have, note gaps. | +| Use AI training knowledge for company descriptions | Every company description must come from live web research, not memory. | +| Forget to score activity levels from heat scores | Heat score has explicit thresholds: High (60+), Medium (30-59), Low (1-29), Dormant (0). | + +--- + +## Step 1: Setup Check + +Check that required API keys are accessible for the channels the user's platform supports: + +```bash +if [ -z "$TAVILY_API_KEY" ]; then echo "TAVILY_API_KEY: NOT SET -- required for web enrichment"; else echo "TAVILY_API_KEY: configured"; fi +if [ -z "$GITHUB_TOKEN" ]; then echo "GITHUB_TOKEN: not set -- GitHub API rate limited to 60 req/hr"; else echo "GITHUB_TOKEN: configured"; fi +``` + +The specific skills being orchestrated have their own API key requirements. Check each skill's SKILL.md for details. Required for full operation: +- `TAVILY_API_KEY` -- web search and company enrichment (get at app.tavily.com) +- `GITHUB_TOKEN` -- GitHub API access (get at github.com/settings/tokens) + +If `TAVILY_API_KEY` is missing: stop and tell the user. Without it, company profiling and web enrichment cannot operate. + +--- + +## Step 2: Parse Input + +Collect from the conversation: +- `companies`: list of company names/URLs to track (required, min 1, max 10 per run) +- `output_preference`: "full report" (default) or "alert-only" or "briefing-only" +- `timeframe`: "realtime" (default) or "last-week" or "last-month" + +**If the user gives a single company name:** still run full radar pipeline. Single-company radars are valid -- get the full profile. + +**If more than 10 companies:** tell the user "Maximum 10 companies per radar scan. I'll run the first 10. Let me know if you want to swap any out." + +Ask if any companies have specific known handles: +- GitHub org name (if different from company name) +- Twitter handle +- YC batch (if YC company) +- Product Hunt slug + +This saves research time. If unknown, the profile phase will discover them. + +--- + +## Step 3: Company Profile Phase + +For each company, build a basic profile before running platform research. + +### Step 3a: Initial Web Enrichment + +For each company, run a Tavily search to discover: + +```text +[company name] official website twitter github linkedin producthunt yc founders +``` + +Extract from search results: +- Domain / website URL +- Description (2-3 sentences) +- Twitter handle (from twitter.com/X.com URLs in results) +- GitHub org (from github.com URLs in results) +- LinkedIn URL +- Product Hunt slug +- YC batch and URL (if applicable) +- Founder names and Twitter handles + +**Output format:** For each company, produce a profile object following `references/company-profile-format.md`. + +### Step 3b: Confirm With User + +Display the discovered profiles and ask the user to confirm or correct before proceeding. + +```markdown +## Discovered Company Profiles + +| Company | Domain | Twitter | GitHub | YC Batch | Founders | +|---|---|---|---|---|---| +| ... | ... | ... | ... | ... | ... | + +Correct any incorrect handles before I proceed to signal collection? +``` + +Wait for user confirmation. Do not skip this step -- wrong handles produce wrong signals. + +--- + +## Step 4: Parallel Signal Collection + +Now run research across all platforms **in parallel** for all confirmed companies. + +### Signal Collection Map + +For each platform, use the appropriate method. Run ALL platforms simultaneously -- do not sequence them. + +#### GitHub Signal +Use web search (Tavily) to find GitHub org, then search for: +```text +github.com/[org] stars forks commits +``` + +Extract: +- Total stars across repos +- Total forks +- Recent commits (last 7 days) +- Recent releases (last 30 days) +- Last push date +- Primary language +- Open issue count + +**Or** call `gh-issue-to-demand-signal` skill if you want deeper demand signal analysis from GitHub Issues. + +#### Twitter/X Signal +Use `twitter-GTM-find-skill` or Tavily search: +```text +twitter.com/[handle] site:twitter.com [company] startup +``` + +Extract: +- Recent tweet count (last 24h) +- Mention volume +- Founder tweet activity +- Key topics/hashtags + +#### Reddit Signal +Use `reddit-icp-monitor` approach or Tavily search: +```text +site:reddit.com [company name] [product category] +``` + +Extract: +- Mention count +- Post scores (upvotes) +- Sentiment (positive/negative/mixed) +- Key complaints or praises +- Relevant subreddits + +#### Hacker News Signal +Use `hackernews-intel` approach or HN Algolia API search: +```text +site:news.ycombinator.com [company name] +``` + +Extract: +- Story count +- Total points +- Front-page stories +- Key topics + +#### Product Hunt Signal +Use `producthunt-launch-kit` approach or Tavily search: +```text +site:producthunt.com [company name] products +``` + +Extract: +- Recent launches +- Upvote count +- Comments/sentiment +- Launch frequency + +#### YC Jobs Signal +Use `yc-intent-radar-skill` / `yc-jobs-scraper` approach or Tavily search: +```text +site:workatastartup.com [company name] OR site:ycombinator.com/companies [company name] +``` + +Extract: +- Open job count +- Job titles/roles +- Department breakdown (Engineering, Sales, Marketing, etc.) +- Location/remote status + +#### Web / Press Signal +Use Tavily search: +```text +[company name] funding announcement product launch news 2026 +``` + +Extract: +- Recent funding rounds +- Product launches +- Key hires announced in press +- Partnership announcements + +#### Pricing Signal (optional, run if user wants pricing intel) +Use `pricing-finder` skill or Tavily search: +```text +[company name] pricing plans 2026 +``` + +Extract: +- Pricing tiers +- Plan structure changes +- Free tier vs paid + +### Handling Failures + +- If any channel returns 0 results, note it in the report as "No signal detected" +- If any skill is not available (API key missing), note as "Channel unavailable" +- Never fabricate data from memory. If you cannot find it, mark it as not found. +- One empty channel does not invalidate the full report. + +--- + +## Step 5: Heat Score Computation + +Use the bundled `scripts/heat-score-calc.mjs` to score each company. This script implements the 4-dimension scoring algorithm from `references/heat-score-methodology.md`. + +### How to Run + +Collect all signal data into a JSON file matching this schema: + +```json +{ + "companies": [{ + "name": "CompanyName", + "signals": { + "stars": null, "forks": null, "ph_votes": null, + "commits_week": null, "releases_month": null, + "active_shipping": false, "last_activity_days": null, + "tweets_24h": null, "mentions": null, + "reddit_posts": null, "reddit_score": null, + "hn_stories": null, "hn_points": null, + "youtube_videos": null, + "jobs": null, "dept_count": null, + "sentiment": null, "traction": null + } + }] +} +``` + +Fill in each field with the discovered value. Leave null for anything not found — the script treats null as 0. + +Then run: + +```bash +node scripts/heat-score-calc.mjs --file signals.json +``` + +Or pipe it: + +```bash +echo '{"companies":[...]}' | node scripts/heat-score-calc.mjs +``` + +### What It Returns + +The script outputs JSON with per-company results: + +```json +{ + "generated_at": "2026-05-29T...", + "company_count": 3, + "companies": [ + { + "name": "Vercel", + "heat_score": 89, + "level": "High", + "dimensions": { + "authority": { "score": 25, "max": 25, "breakdown": {...} }, + "shipping": { "score": 25, "max": 25, "breakdown": {...} }, + "social": { "score": 17, "max": 25, "breakdown": {...} }, + "growth": { "score": 22, "max": 25, "breakdown": {...} } + }, + "alerts": [...] + } + ] +} +``` + +Each company includes: +- `heat_score` — total 0-100 +- `level` — High (60+), Medium (30-59), Low (1-29), Dormant (0) +- `dimensions` — per-dimension score with max and itemized breakdown +- `alerts` — auto-detected notable signals + +### Scoring Rules (implemented in script) + +These are the formulas the script applies. They're documented here for transparency: + +| Dimension | Signals | Max | +|---|---|---| +| Authority | GitHub stars (`min(15, stars/1000*3)`), forks (`min(5, forks/200*2)`), PH votes (`min(5, votes/100*5)`) | 25 | +| Shipping | Commits/week (`min(10, commits*2)`), releases/month (5 if >0), active flag (5), recency (5 if <7d, 3 if <30d) | 25 | +| Social | Tweets (5), mentions (5), Reddit posts (3) + score (2), HN stories (4) + points (3), YouTube (3) | 25 | +| Growth | Jobs (`min(10, jobs*3)`), dept diversity (`min(5, dept_count*2)`), AI sentiment (5), AI traction (5) | 25 | + +- Each dimension caps at 25. Missing signals score 0. Never estimate data. +- Full methodology and edge cases in `references/heat-score-methodology.md`. + +--- + +## Step 6: AI Executive Briefing + +For each company scored above 0 (i.e., any signal detected), generate an AI executive briefing using the collected data. + +The briefing must cover: + +``` +**Executive Brief: [Company Name]** + +**Context:** 1-2 sentences on what they do and their market position +**Heat Score:** [score]/100 — [Activity Level] + +**Recent Activity:** +- Product: key product or launch signals found +- Hiring: hiring status, departments, notable roles +- Community: sentiment summary from Reddit/HN/Twitter + +**Threat Assessment:** +- Competitive threat level: [Low / Medium / High] +- Rationale: 2-3 sentences on why + +**Key Signal (most important takeaway):** +One sentence on the single most important thing happening with this company. + +**Data Confidence:** +What channels had good data vs what was missing. +``` + +**Rules:** +- Every claim in the briefing must trace to collected data +- "Data Confidence" section is mandatory -- be honest about gaps +- Threat assessment should compare against the other companies in the radar, not in a vacuum +- Keep each briefing under 250 words + +--- + +## Step 7: Assemble and Output the Radar Report + +Compile everything into the structured radar report format. Use `references/radar-report-template.md` for the exact output structure. + +The report should include: +1. **Executive Summary** — Top-line findings with ranked companies +2. **Heat Score Leaderboard** — Ranked table of all companies +3. **Per-Company Deep Dives** — Each company with full profile, signal data, score breakdown, and AI briefing +4. **Signal Alerts** — Notable events detected (hiring surges, viral moments, launches) +5. **Data Quality Notes** — Which channels had data, which were missing + +Output in markdown format, ready to copy into Slack, Notion, Google Docs, or email. + +--- + +## Step 8: Optional — Schedule Recurring Radar + +If the user wants ongoing monitoring: + +1. Save the company list and API configuration +2. Set up a cron schedule (GitHub Actions or system cron) +3. Each run produces an updated report +4. Configure alerts for score changes (e.g., "alert if any company jumps 20+ points") + +This skill is an orchestrator — each run executes the full pipeline fresh. diff --git a/skills/company-radar/references/company-profile-format.md b/skills/company-radar/references/company-profile-format.md new file mode 100644 index 0000000..90d3066 --- /dev/null +++ b/skills/company-radar/references/company-profile-format.md @@ -0,0 +1,151 @@ +# Company Profile Format + +Standardized company profile object used across all radar phases. Every profile must conform to this structure. + +--- + +## Profile Data Model + +```yaml +company: + name: string # Required. Official company name + domain: string | null # Website domain (e.g., vercel.com) + description: string | null # 2-3 sentence description from web research + logo_url: string | null # URL to company logo if found + + # Social handles + twitter_handle: string | null # Without @ (e.g., "vercel") + github_org: string | null # GitHub org or user name (e.g., "vercel") + linkedin_url: string | null # Full LinkedIn URL + youtube_channel: string | null # YouTube channel handle + reddit_community: string | null # Subreddit name (e.g., "reactjs") + blog_url: string | null # Company blog URL + docs_url: string | null # Documentation URL + careers_url: string | null # Careers / jobs page URL + + # YC info + yc_batch: string | null # e.g., "W21", "S20" + yc_url: string | null # Y Combinator company page URL + + # Product Hunt + producthunt_slug: string | null # PH slug (e.g., "vercel") + producthunt_url: string | null # Full PH URL + + # Founders + founders: + - name: string # Founder full name + title: string | null # e.g., "CEO", "CTO" + twitter_handle: string | null + + # Metadata + is_open_source: boolean # Whether the company has OSS repos + is_yc_company: boolean # Whether it's a YC-backed company + profile_completeness: integer # 0-100, how complete the profile is + source_urls: string[] # URLs used to build this profile +``` + +--- + +## Profile Rules + +1. **Every field must come from evidence.** No default values, no guesses. +2. If a handle/URL is not found, set to `null` -- do not invent it. +3. `profile_completeness` = percentage of discoverable fields filled. A company with domain + description + at least one social handle is ~40% complete. Full social handles + YC + founders = ~90%+. +4. `source_urls` must include the actual URLs where each piece of info was found. +5. Founders should only include confirmed founders (not employees, advisors, or investors). + +--- + +## Profile Discovery Flow + +When building a company profile from scratch: + +``` +1. Start with company name and/or domain from user input +2. Run Tavily search: "[name] official website twitter github linkedin producthunt yc" +3. Parse search results for social handles and URLs +4. Visit the company website (if found) for description and positioning +5. Search YC: "site:ycombinator.com/companies [name]" for YC batch info +6. Search founders: "[name] founder ceo twitter" for each likely founder +7. Fill profile fields from discovered data +8. Compute profile_completeness +``` + +--- + +## Profile Examples + +### High-Completeness Profile + +```yaml +company: + name: Vercel + domain: vercel.com + description: "Vercel is the platform for frontend developers, providing the speed and reliability innovators need to create at the moment of inspiration." + logo_url: "https://vercel.com/api/logo" + + twitter_handle: "vercel" + github_org: "vercel" + linkedin_url: "https://linkedin.com/company/vercel" + youtube_channel: "vercel" + reddit_community: null + blog_url: "https://vercel.com/blog" + docs_url: "https://vercel.com/docs" + careers_url: "https://vercel.com/careers" + + yc_batch: null + yc_url: null + + producthunt_slug: "vercel" + producthunt_url: "https://www.producthunt.com/@vercel" + + founders: + - name: "Guillermo Rauch" + title: "CEO" + twitter_handle: "rauchg" + - name: "Tim Neutkens" + title: "CTO" + twitter_handle: "timneutkens" + + is_open_source: true + is_yc_company: false + profile_completeness: 95 + source_urls: + - "https://vercel.com" + - "https://github.com/vercel" + - "https://twitter.com/vercel" +``` + +### Low-Completeness Profile + +```yaml +company: + name: "ACME Software" + domain: "acmesoftware.io" + description: null # not found in search + logo_url: null + + twitter_handle: "acmesoftware" + github_org: null + linkedin_url: null + youtube_channel: null + reddit_community: null + blog_url: null + docs_url: null + careers_url: null + + yc_batch: null + yc_url: null + + producthunt_slug: null + producthunt_url: null + + founders: [] + + is_open_source: false + is_yc_company: false + profile_completeness: 15 + source_urls: + - "https://acmesoftware.io" + - "https://twitter.com/acmesoftware" +``` diff --git a/skills/company-radar/references/heat-score-methodology.md b/skills/company-radar/references/heat-score-methodology.md new file mode 100644 index 0000000..9895156 --- /dev/null +++ b/skills/company-radar/references/heat-score-methodology.md @@ -0,0 +1,116 @@ +# Heat Score Methodology + +The Company Radar heat score is a 0-100 composite score computed from four equally-weighted dimensions. It measures competitive intensity and momentum -- the higher the score, the more competitive activity the company is generating. + +--- + +## Dimension Breakdown + +### 1. Authority (0-25) +Baseline credibility and community validation. + +| Signal | Max Points | Formula | Data Source | +|---|---|---|---| +| GitHub Stars | 15 | `min(15, (stars / 1000) * 3)` | GitHub search / API | +| GitHub Forks | 5 | `min(5, (forks / 200) * 2)` | GitHub search / API | +| Product Hunt Votes | 5 | `min(5, (votes / 100) * 5)` | PH search / API | + +**Interpretation:** +- 15+ stars (15 pts): Established community-validated product +- 5-15 stars (7-14 pts): Growing traction +- <5 stars (<7 pts): Early stage or low community traction + +### 2. Shipping (0-25) +Product velocity and development activity. + +| Signal | Max Points | Formula | Data Source | +|---|---|---|---| +| Commits This Week | 10 | `min(10, commits * 2)` | GitHub search | +| Releases This Month | 5 | `5 if releases > 0 else 0` | GitHub releases | +| Actively Shipping | 5 | `5 if actively_shipping else 0` | Push recency + commit consistency | +| Days Since Last Activity | 5 | `5 if <7d, 3 if <30d, 0 otherwise` | Last push date | + +**Interpretation:** +- 20+ pts: Shipping multiple times per week, very active +- 10-19 pts: Regular shipping cadence +- <10 pts: Infrequent or stalled development + +### 3. Social (0-25) +Visibility, mindshare, and community buzz. + +| Signal | Max Points | Formula | Data Source | +|---|---|---|---| +| Tweet Count (24h) | 5 | `min(5, tweets * 1)` | Twitter search / skill | +| Mention Count | 5 | `min(5, mentions * 2)` | Twitter search | +| Reddit Posts | 3 | `min(3, posts * 1.5)` | Reddit search / skill | +| Reddit Score | 2 | `min(2, (score / 100) * 2)` | Reddit search | +| HN Stories | 4 | `min(4, stories * 2)` | HN search / skill | +| HN Points | 3 | `min(3, (points / 200) * 3)` | HN search | +| YouTube / Video | 3 | `min(3, videos * 1)` | Web search | + +**Interpretation:** +- 20+ pts: Significant social presence, possibly viral +- 10-19 pts: Consistent community engagement +- <10 pts: Low social footprint + +### 4. Growth (0-25) +Expansion indicators -- hiring, sentiment, traction. + +| Signal | Max Points | Formula | Data Source | +|---|---|---|---| +| Open Job Count | 10 | `min(10, jobs * 3)` | YC Jobs / careers page | +| Hiring Department Diversity | 5 | `min(5, dept_count * 2)` | YC Jobs / job listings | +| Community Sentiment (AI) | 5 | `min(5, (sentiment / 100) * 5)` | AI analysis of Reddit/HN/Twitter | +| Product Traction (AI) | 5 | `min(5, (traction / 100) * 5)` | AI analysis of signals | + +**Interpretation:** +- 20+ pts: Rapidly scaling team, high market demand +- 10-19 pts: Measured growth, building team +- <10 pts: Early stage or steady state + +--- + +## Activity Level Thresholds + +| Heat Score | Activity Level | Color | Meaning | +|---|---|---|---| +| 60-100 | **High** | Red | Company is very active across multiple signals -- competitive threat | +| 30-59 | **Medium** | Yellow | Moderate activity, some channels active -- worth watching | +| 1-29 | **Low** | Blue | Minimal detectable activity -- low immediate threat | +| 0 | **Dormant** | Gray | No signals detected -- inactive or not found | + +--- + +## Computation Rules + +1. **Score each dimension independently**, then sum for final heat score (0-100) +2. Each dimension caps at **25 points** -- cannot overscore on one dimension +3. If a signal value is **unknown** (not found), score it as **0** +4. If ALL data for a dimension is missing, the dimension scores 0 +5. **Never estimate or round up** -- use exact formulas with available data +6. A company with 0 on all dimensions is "Dormant" -- but still include in report + +### Edge Cases + +| Situation | Handling | +|---|---| +| No GitHub org found | Authority and Shipping score 0 for GH signals | +| Company is private (no GH) | Partial score from PH, Social, Growth dimensions only | +| No social handles found | Social dimension scores 0 | +| Not hiring / no job listings | Growth dimension scores 0 (no hiring is a signal too) | +| Only 1-2 channels have data | Score what you have, note data gaps in report | +| Multiple founders active on Twitter | Count all founder tweets combined, cap at Social max | + +--- + +## Worked Example + +**Company: Vercel** + +| Dimension | Raw Data | Computed Score | +|---|---|---| +| Authority | 60k GH stars, 5k forks, 2k PH votes | 15 + 5 + 5 = **25/25** | +| Shipping | 45 commits/week, 8 releases/month, active daily | 10 + 5 + 5 + 5 = **25/25** | +| Social | 12 tweets/day, 30 mentions, 5 HN stories, 3 Reddit posts | 5 + 5 + 4 + 3 = **17/25** | +| Growth | 15 open jobs, 4 depts hiring, positive sentiment | 10 + 5 + 4 + 3 = **22/25** | +| **Total** | | **89/100 -- High** | diff --git a/skills/company-radar/references/radar-report-template.md b/skills/company-radar/references/radar-report-template.md new file mode 100644 index 0000000..cddf1ca --- /dev/null +++ b/skills/company-radar/references/radar-report-template.md @@ -0,0 +1,187 @@ +# Radar Report Template + +One output template for all radar runs. The structure is fixed. Fill in all brackets from collected data. No brackets should appear in the final output. + +--- + +## Report Header + +``` +# Company Radar Report + +**Generated:** [date] +**Companies tracked:** [N] +**Timeframe:** [realtime / last-week / last-month] +**Channels scanned:** GitHub, Twitter/X, Reddit, Hacker News, Product Hunt, YC Jobs, Web, [other] + +--- + +## Executive Summary + +[2-3 paragraph synthesis of the competitive landscape. Rank companies by heat score. +Call out the biggest movers, most interesting signals, and any urgent alerts.] + +**Top-line rankings:** +1. [Company A] — [score]/100 — [activity level] +2. [Company B] — [score]/100 — [activity level] +3. [Company C] — [score]/100 — [activity level] + +**Key alerts this run:** [N] notable signals detected +``` + +--- + +## Heat Score Leaderboard + +``` +| Rank | Company | Heat Score | Activity | Authority | Shipping | Social | Growth | Hiring? | +|---|---|---|---|---|---|---|---|---| +| 1 | [Name] | [0-100] | [High/Med/Low/Dormant] | [0-25] | [0-25] | [0-25] | [0-25] | [Yes/No] | +| 2 | [Name] | [0-100] | [High/Med/Low/Dormant] | [0-25] | [0-25] | [0-25] | [0-25] | [Yes/No] | +``` + +--- + +## Per-Company Deep Dives + +Repeat for each company. Order by heat score (highest first). + +``` +--- + +## [Company Name] + +**Profile:** [description from web research] +**Domain:** [url] +**Twitter:** [@handle or "Not found"] +**GitHub:** [org or "Not found"] +**YC Batch:** [batch or "N/A"] +**Founders:** [names with Twitter handles] + +### Heat Score: [score]/100 — [Activity Level] + +| Dimension | Score | Key Drivers | +|---|---|---| +| Authority | [0-25] | [key data points] | +| Shipping | [0-25] | [key data points] | +| Social | [0-25] | [key data points] | +| Growth | [0-25] | [key data points] | + +### Signal Details + +**GitHub:** +- Stars: [N] | Forks: [N] | Commits/Week: [N] +- Releases/Month: [N] | Last push: [date] +- Primary language: [lang] +- [Notes on shipping velocity] + +**Twitter/X:** +- Tweets (24h): [N] | Mentions: [N] +- Founder activity: [summary] +- Key topics: [topics] + +**Reddit:** +- Mentions: [N] | Total score: [N] +- Sentiment: [positive/negative/mixed] +- Key threads: [top 2-3 thread titles] + +**Hacker News:** +- Stories: [N] | Total points: [N] +- Front page stories: [N] +- Key discussions: [top 1-2 story titles] + +**Product Hunt:** +- Recent launches: [N] +- Total votes: [N] +- Launch frequency: [High/Medium/Low/None] + +**YC Jobs:** +- Open roles: [N] +- Departments hiring: [list] +- Notable roles: [top 2-3 titles] + +**Web / Press:** +- Funding: [details or "None detected"] +- Product launches: [details or "None"] +- Key news: [top 1-2 items] + +### Executive Briefing + +[AI-generated briefing following the format from SKILL.md Step 6] + +### Alerts + +| Type | Severity | Detail | +|---|---|---| +| [Alert type] | [High/Med/Low] | [Description] | +``` + +--- + +## Alerts Summary + +``` +## Alerts This Run + +| Severity | Type | Company | Description | +|---|---|---|---| +| 🔴 High | [Type] | [Company] | [Summary] | +| 🟡 Medium | [Type] | [Company] | [Summary] | +| 🟢 Low | [Type] | [Company] | [Summary] | +``` + +--- + +## Data Quality Notes + +``` +## Data Quality + +| Company | GitHub | Twitter | Reddit | HN | PH | YC Jobs | Web | +|---|---|---|---|---|---|---|---| +| [A] | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | +| [B] | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | ✅/❌ | + +**Notes:** +- [Channel X] had no data for [reason]. Score may be understated. +- [Company Y] missing GitHub because org not found. +- [Channel Z] API key not configured. +``` + +--- + +## Worked Example (Truncated) + +``` +# Company Radar Report + +**Generated:** 2026-05-29 +**Companies tracked:** 3 +**Channels scanned:** GitHub, Twitter/X, Reddit, Hacker News, Product Hunt, YC Jobs, Web + +--- + +## Executive Summary + +Vercel leads the pack with a heat score of 89 (High activity), driven by massive GitHub +authority and active shipping. Netlify is close behind at 72, with strong social presence +but slower shipping velocity. Railway is the dark horse at 45, showing medium activity with +interesting hiring signals that suggest a growth phase. + +**Top-line rankings:** +1. Vercel — 89/100 — High +2. Netlify — 72/100 — High +3. Railway — 45/100 — Medium + +**Key alerts this run:** 2 notable signals (Vercel GH star surge, Railway hiring spike) + +--- + +## Heat Score Leaderboard + +| Rank | Company | Heat Score | Activity | Authority | Shipping | Social | Growth | Hiring? | +|---|---|---|---|---|---|---|---|---| +| 1 | Vercel | 89 | High | 25 | 25 | 17 | 22 | Yes | +| 2 | Netlify | 72 | High | 20 | 15 | 22 | 15 | Yes | +| 3 | Railway | 45 | Medium | 8 | 12 | 10 | 15 | Yes | +``` diff --git a/skills/company-radar/references/skill-integration-map.md b/skills/company-radar/references/skill-integration-map.md new file mode 100644 index 0000000..df79d89 --- /dev/null +++ b/skills/company-radar/references/skill-integration-map.md @@ -0,0 +1,280 @@ +# Skill Integration Map + +How to call each opendirectory skill for radar signal collection. Every channel has either a dedicated skill or a web search fallback. + +--- + +## 1. GitHub Signal + +### Primary: `gh-issue-to-demand-signal` +Use this skill when you need deeper demand signal analysis from GitHub Issues. + +**Trigger phrase:** "Find demand signals from GitHub issues for [org/repo]" + +**What it returns:** Clustered demand categories with scores, GTM messaging briefs, ranked issue list. + +**Limitation:** This skill analyzes *issues*, not general repo health. For stars/forks/commits, use the web search fallback below. + +### Fallback: Tavily Search +```text +github.com/[org] stars forks commits +``` + +**What to extract:** Total stars, forks, recent commits, releases, last push date, primary language, open issues. + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| total_stars | GitHub search / API | Yes | +| total_forks | GitHub search / API | Yes | +| commits_this_week | GitHub search (commits feed) | Yes | +| releases_this_month | GitHub releases tab | Yes | +| last_push_date | GitHub repo page | Yes | +| primary_language | GitHub repo page | Nice-to-have | +| open_issues | GitHub search / API | Nice-to-have | + +--- + +## 2. Twitter/X Signal + +### Primary: `twitter-GTM-find-skill` +Use this skill to scrape company and founder Twitter activity. + +**Trigger phrase:** "Find GTM talent / activity on Twitter for [company/handle]" + +**What it returns:** Tweet data, follower counts, activity patterns. + +**Limitation:** This skill is optimized for finding GTM roles, not general social monitoring. For basic tweet counts, use Tavily search. + +### Fallback: Tavily Search +```text +site:twitter.com [handle] OR site:x.com [handle] +``` + +**What to extract:** Recent tweet count, mentions, key topics/hashtags, engagement levels. + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| tweet_count_24h | Twitter search | Yes | +| mention_count | Twitter search | Nice-to-have | +| founder_tweet_activity | Founder handle search | Yes | +| key_topics | Tweet content analysis | Nice-to-have | + +--- + +## 3. Reddit Signal + +### Primary: `reddit-icp-monitor` +Use this skill to monitor Reddit for company mentions and sentiment. + +**Trigger phrase:** "Monitor Reddit for [company name] mentions and sentiment" + +**What it returns:** Ranked posts with ICP scores, pain point summaries, draft replies. + +### Secondary: `reddit-post-engine` +Use when you need to understand subreddit culture around this company's space. + +**Trigger phrase:** "Analyze Reddit posts about [company] in [subreddit]" + +### Fallback: Tavily Search +```text +site:reddit.com [company name] [category] +``` + +**What to extract:** Post count, scores (upvotes), sentiment, subreddits, key thread titles. + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| mention_count | Reddit search | Yes | +| total_score | Sum of post scores | Yes | +| sentiment | Content analysis | Yes | +| top_threads | Reddit search | Nice-to-have | +| relevant_subreddits | Reddit search | Nice-to-have | + +--- + +## 4. Hacker News Signal + +### Primary: `hackernews-intel` +Use this skill to monitor HN for company mentions. + +**Trigger phrase:** "Monitor Hacker News for [company name]" + +**What it returns:** Matching HN posts with points, deduplicated against SQLite cache, Slack alerts. + +**Setup required:** `HN_KEYWORDS` and `SLACK_WEBHOOK` environment variables. If not configured, use fallback. + +### Fallback: HN Algolia API + Tavily +```text +site:news.ycombinator.com [company name] +``` + +Or direct Algolia API: +```text +https://hn.algolia.com/api/v1/search?query=[company]&tags=story +``` + +**What to extract:** Story count, total points, front-page stories, key discussion topics. + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| story_count | HN search / API | Yes | +| total_points | HN search / API | Yes | +| front_page_stories | HN search / API | Nice-to-have | +| top_stories | HN search | Nice-to-have | + +--- + +## 5. Product Hunt Signal + +### Primary: `producthunt-launch-kit` +Use this skill to research Product Hunt presence. + +**Trigger phrase:** "Prepare a Product Hunt launch analysis for [company name]" + +**What it returns:** Launch assets, taglines, post drafts, launch strategy. + +### Fallback: Tavily Search +```text +site:producthunt.com [company name] products +``` + +**What to extract:** Recent launches, upvotes, comments, launch frequency. + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| recent_launches | PH search | Yes | +| total_votes | PH search | Yes | +| launch_frequency | PH search | Nice-to-have | +| recent_products | PH search | Nice-to-have | + +--- + +## 6. YC Jobs Signal + +### Primary: `yc-intent-radar-skill` / `yc-jobs-scraper` +Use this skill to scrape Y Combinator job listings. + +**Trigger phrase:** "Scrape YC jobs for [company name]" + +**What it returns:** Company slugs, job listings with IDs, deduplicated SQLite database, JSON export of radar candidates. + +**Scripts available:** +```bash +cd scripts +node auth.js # First-time auth (manual login) +node scraper.js # Scrape all YC jobs +node export_radar_candidates.js # Export targeted roles to JSON +``` + +### Fallback: Tavily Search +```text +site:workatastartup.com [company name] OR site:ycombinator.com/companies [company name] +``` + +**What to extract:** Open job count, job titles, departments, locations. + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| job_count | YC jobs search | Yes | +| job_titles | YC jobs search | Yes | +| department_breakdown | Job title analysis | Yes | +| locations | YC jobs search | Nice-to-have | + +--- + +## 7. Web / Press Signal + +### Primary: Tavily Search + `competitor-pr-finder` + +Use Tavily search directly for press signals: +```text +[company name] funding announcement product launch 2026 +``` + +For PR opportunity analysis, use `competitor-pr-finder`: +**Trigger phrase:** "Find PR opportunities for [company name]" + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| funding_rounds | Tavily search | Nice-to-have | +| product_launches | Tavily search | Nice-to-have | +| press_mentions | Tavily search | Nice-to-have | +| partnerships | Tavily search | Nice-to-have | + +--- + +## 8. Pricing Signal (Optional) + +### Primary: `pricing-finder` +Use this skill for detailed pricing research. + +**Trigger phrase:** "Find pricing for [company name] competitors" + +**What it returns:** Competitor pricing tiers, feature gate analysis, competitive positioning map, recommended strategy. + +### Fallback: Tavily Search +```text +[company name] pricing plans 2026 +``` + +### Data Points Collected + +| Field | Source | Required? | +|---|---|---| +| pricing_tiers | Web search | Optional | +| plan_structure | Web search | Optional | +| free_tier_info | Web search | Optional | + +--- + +## 9. Market Positioning (Optional Deep Dive) + +### Primary: `map-your-market` +Use this skill for comprehensive market mapping. + +**Trigger phrase:** "Map the market for [product category]" + +**What it returns:** ICP definition, ranked pain themes with verbatim quotes, market size signals, messaging angles. + +**Not a per-company tool -- use this to understand the broader competitive landscape, not an individual company.** + +--- + +## Orchestration Pattern + +When calling multiple skills in one radar run, use this parallel execution pattern: + +```text +For each company in [company list]: + PARALLEL: + - Run GitHub research (web search or gh-issue-to-demand-signal) + - Run Twitter research (web search or twitter-GTM-find-skill) + - Run Reddit research (web search or reddit-icp-monitor) + - Run HN research (web search or hackernews-intel) + - Run PH research (web search or producthunt-launch-kit) + - Run YC Jobs research (web search or yc-jobs-scraper) + - Run Web/Press research (Tavily search) + + After ALL parallel tasks complete: + - Compute heat score + - Generate AI briefing + - Add to report + +Combine all company reports into single radar document. +``` + +**Never run channels sequentially.** All 8 channels are independent. Running them in sequence wastes 8x the time. diff --git a/skills/company-radar/scripts/heat-score-calc.mjs b/skills/company-radar/scripts/heat-score-calc.mjs new file mode 100644 index 0000000..624a427 --- /dev/null +++ b/skills/company-radar/scripts/heat-score-calc.mjs @@ -0,0 +1,140 @@ +/** + * Company Radar heat score calculator. + * 4 dimensions (Authority, Shipping, Social, Growth), each max 25, total 0-100. + * Usage: node heat-score-calc.mjs --file signals.json + * Input: JSON with companies[] containing signal fields. + * Output: JSON with scored results, dimension breakdowns, and alerts. + */ + +import { readFileSync } from 'fs'; + +function scoreAuthority(signals) { + const stars = Number(signals.stars) || 0; + const forks = Number(signals.forks) || 0; + const phVotes = Number(signals.ph_votes) || 0; + const breakdown = { + stars: Math.min(15, (stars / 1000) * 3), + forks: Math.min(5, (forks / 200) * 2), + ph_votes: Math.min(5, (phVotes / 100) * 5) + }; + const total = breakdown.stars + breakdown.forks + breakdown.ph_votes; + return { score: Math.min(25, total), max: 25, breakdown }; +} + +function scoreShipping(signals) { + const commits = Number(signals.commits_week) || 0; + const releases = Number(signals.releases_month) || 0; + const daysSince = signals.last_activity_days ?? 999; + const breakdown = { + commits_week: Math.min(10, commits * 2), + releases_month: releases > 0 ? 5 : 0, + active_shipping: signals.active_shipping === true ? 5 : 0, + recency: daysSince < 7 ? 5 : (daysSince < 30 ? 3 : 0) + }; + const total = breakdown.commits_week + breakdown.releases_month + breakdown.active_shipping + breakdown.recency; + return { score: Math.min(25, total), max: 25, breakdown }; +} + +function scoreSocial(signals) { + const breakdown = { + tweets_24h: Math.min(5, (Number(signals.tweets_24h) || 0) * 1), + mentions: Math.min(5, (Number(signals.mentions) || 0) * 2), + reddit_posts: Math.min(3, (Number(signals.reddit_posts) || 0) * 1.5), + reddit_score: Math.min(2, ((Number(signals.reddit_score) || 0) / 100) * 2), + hn_stories: Math.min(4, (Number(signals.hn_stories) || 0) * 2), + hn_points: Math.min(3, ((Number(signals.hn_points) || 0) / 200) * 3), + youtube_videos: Math.min(3, (Number(signals.youtube_videos) || 0) * 1) + }; + const total = Object.values(breakdown).reduce((a, b) => a + b, 0); + return { score: Math.min(25, total), max: 25, breakdown }; +} + +function scoreGrowth(signals) { + const breakdown = { + jobs: Math.min(10, (Number(signals.jobs) || 0) * 3), + dept_diversity: Math.min(5, (Number(signals.dept_count) || 0) * 2), + ai_sentiment: Math.min(5, ((Number(signals.sentiment) || 0) / 100) * 5), + ai_traction: Math.min(5, ((Number(signals.traction) || 0) / 100) * 5) + }; + const total = Object.values(breakdown).reduce((a, b) => a + b, 0); + return { score: Math.min(25, total), max: 25, breakdown }; +} + +function activityLevel(score) { + if (score >= 60) return 'High'; + if (score >= 30) return 'Medium'; + if (score >= 1) return 'Low'; + return 'Dormant'; +} + +function generateAlerts(name, dims, signals) { + const alerts = []; + if ((Number(signals.jobs) || 0) >= 5) + alerts.push({ type: 'hiring_spike', severity: 'medium', message: `${name} has ${signals.jobs} open roles` }); + if ((Number(signals.tweets_24h) || 0) >= 20) + alerts.push({ type: 'high_tweet_volume', severity: 'medium', message: `${name} tweeted ${signals.tweets_24h} times in 24h` }); + if ((Number(signals.commits_week) || 0) >= 30) + alerts.push({ type: 'high_shipping_velocity', severity: 'low', message: `${name} shipped ${signals.commits_week} commits this week` }); + if (dims.social.score >= 20) + alerts.push({ type: 'strong_social_presence', severity: 'low', message: `${name} has high social engagement (${Math.round(dims.social.score)}/25)` }); + if (dims.growth.score >= 20) + alerts.push({ type: 'strong_growth_signals', severity: 'medium', message: `${name} shows strong growth signals (${Math.round(dims.growth.score)}/25)` }); + return alerts; +} + +function computeCompany(company) { + const { name, signals } = company; + const authority = scoreAuthority(signals); + const shipping = scoreShipping(signals); + const social = scoreSocial(signals); + const growth = scoreGrowth(signals); + + const total = Math.round(authority.score + shipping.score + social.score + growth.score); + return { + name, + heat_score: total, + level: activityLevel(total), + dimensions: { authority, shipping, social, growth }, + alerts: generateAlerts(name, { authority, shipping, social, growth }, signals) + }; +} + +function parseInput(raw) { + try { return JSON.parse(raw); } + catch { console.error('Invalid JSON input'); process.exit(1); } +} + +function main() { + const args = process.argv.slice(2); + const fileIndex = args.indexOf('--file'); + + if (fileIndex !== -1 && args[fileIndex + 1]) { + const input = parseInput(readFileSync(args[fileIndex + 1], 'utf-8')); + const companies = input.companies || [input]; + const result = { + generated_at: new Date().toISOString(), + company_count: companies.length, + companies: companies.map(computeCompany) + }; + process.stdout.write(JSON.stringify(result, null, 2) + '\n'); + } else if (!process.stdin.isTTY) { + const chunks = []; + process.stdin.on('data', chunk => chunks.push(chunk)); + process.stdin.on('end', () => { + const input = parseInput(Buffer.concat(chunks).toString('utf-8')); + const companies = input.companies || [input]; + const result = { + generated_at: new Date().toISOString(), + company_count: companies.length, + companies: companies.map(computeCompany) + }; + process.stdout.write(JSON.stringify(result, null, 2) + '\n'); + }); + } else { + console.error('Usage: node heat-score-calc.mjs --file '); + console.error(' or: cat signals.json | node heat-score-calc.mjs'); + process.exit(1); + } +} + +main(); From 649c37217b1c729b03d352640e031b9e1fd8083e Mon Sep 17 00:00:00 2001 From: Fariz Anjum Date: Fri, 29 May 2026 20:33:33 +0530 Subject: [PATCH 2/4] fix(company-radar): clamp reddit score, guard missing signals, handle readFileSync errors Clamp reddit_score at 0 to prevent negative Social dimension scores Guard against missing signals field in computeCompany with early return Wrap readFileSync in try/catch for cleaner CLI error messages Ultraworked with Sisyphus (https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- skills/company-radar/references/heat-score-methodology.md | 6 +++--- skills/company-radar/scripts/heat-score-calc.mjs | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/skills/company-radar/references/heat-score-methodology.md b/skills/company-radar/references/heat-score-methodology.md index 9895156..eab2ded 100644 --- a/skills/company-radar/references/heat-score-methodology.md +++ b/skills/company-radar/references/heat-score-methodology.md @@ -16,9 +16,9 @@ Baseline credibility and community validation. | Product Hunt Votes | 5 | `min(5, (votes / 100) * 5)` | PH search / API | **Interpretation:** -- 15+ stars (15 pts): Established community-validated product -- 5-15 stars (7-14 pts): Growing traction -- <5 stars (<7 pts): Early stage or low community traction +- 5,000+ stars (15 pts): Established community-validated product +- 1,500-5,000 stars (5-14 pts): Growing traction +- <1,500 stars (<5 pts): Early stage or low community traction ### 2. Shipping (0-25) Product velocity and development activity. diff --git a/skills/company-radar/scripts/heat-score-calc.mjs b/skills/company-radar/scripts/heat-score-calc.mjs index 624a427..10ba29f 100644 --- a/skills/company-radar/scripts/heat-score-calc.mjs +++ b/skills/company-radar/scripts/heat-score-calc.mjs @@ -40,7 +40,7 @@ function scoreSocial(signals) { tweets_24h: Math.min(5, (Number(signals.tweets_24h) || 0) * 1), mentions: Math.min(5, (Number(signals.mentions) || 0) * 2), reddit_posts: Math.min(3, (Number(signals.reddit_posts) || 0) * 1.5), - reddit_score: Math.min(2, ((Number(signals.reddit_score) || 0) / 100) * 2), + reddit_score: Math.max(0, Math.min(2, ((Number(signals.reddit_score) || 0) / 100) * 2)), hn_stories: Math.min(4, (Number(signals.hn_stories) || 0) * 2), hn_points: Math.min(3, ((Number(signals.hn_points) || 0) / 200) * 3), youtube_videos: Math.min(3, (Number(signals.youtube_videos) || 0) * 1) @@ -84,6 +84,7 @@ function generateAlerts(name, dims, signals) { function computeCompany(company) { const { name, signals } = company; + if (!signals) return { name, heat_score: 0, level: 'Dormant', dimensions: { authority: {score:0,max:25,breakdown:{}}, shipping: {score:0,max:25,breakdown:{}}, social: {score:0,max:25,breakdown:{}}, growth: {score:0,max:25,breakdown:{}} }, alerts: [] }; const authority = scoreAuthority(signals); const shipping = scoreShipping(signals); const social = scoreSocial(signals); @@ -109,7 +110,7 @@ function main() { const fileIndex = args.indexOf('--file'); if (fileIndex !== -1 && args[fileIndex + 1]) { - const input = parseInput(readFileSync(args[fileIndex + 1], 'utf-8')); + let raw; try { raw = readFileSync(args[fileIndex + 1], 'utf-8'); } catch (e) { console.error('Cannot read file: ' + args[fileIndex + 1] + ' (' + e.message + ')'); process.exit(1); } const input = parseInput(raw); const companies = input.companies || [input]; const result = { generated_at: new Date().toISOString(), From 468fbc06f926e3e99256af865aaf0ef7a8fc6aae Mon Sep 17 00:00:00 2001 From: Fariz Anjum Date: Fri, 29 May 2026 20:33:37 +0530 Subject: [PATCH 3/4] docs(company-radar): fix typo, add heat-score-only output mode Fix ranked rankings -> ranked companies in README Document heat-score-only as valid output_preference in SKILL.md Ultraworked with Sisyphus (https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- skills/company-radar/README.md | 2 +- skills/company-radar/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/skills/company-radar/README.md b/skills/company-radar/README.md index 2bc8979..35a7111 100644 --- a/skills/company-radar/README.md +++ b/skills/company-radar/README.md @@ -125,7 +125,7 @@ Runs the radar and compares scores with the previous run to show deltas. The skill produces a single structured markdown report containing: -- **Executive Summary** -- landscape-level synthesis, ranked rankings, key alerts +- **Executive Summary** -- landscape-level synthesis, ranked companies, key alerts - **Heat Score Leaderboard** -- table of all tracked companies sorted by score - **Per-Company Deep Dives** -- full signal detail per channel, heat score breakdown, AI executive briefing - **Alerts Summary** -- notable signals grouped by severity diff --git a/skills/company-radar/SKILL.md b/skills/company-radar/SKILL.md index 1f63f01..6101bef 100644 --- a/skills/company-radar/SKILL.md +++ b/skills/company-radar/SKILL.md @@ -82,7 +82,7 @@ If `TAVILY_API_KEY` is missing: stop and tell the user. Without it, company prof Collect from the conversation: - `companies`: list of company names/URLs to track (required, min 1, max 10 per run) -- `output_preference`: "full report" (default) or "alert-only" or "briefing-only" +- `output_preference`: "full report" (default), "alert-only", "briefing-only", or "heat-score-only" (leaderboard table + scores only, no deep dives) - `timeframe`: "realtime" (default) or "last-week" or "last-month" **If the user gives a single company name:** still run full radar pipeline. Single-company radars are valid -- get the full profile. From ea799c0c93bf09aba12b26d7cbd3e6979be54e75 Mon Sep 17 00:00:00 2001 From: Fariz Anjum Date: Fri, 29 May 2026 20:33:41 +0530 Subject: [PATCH 4/4] fix(scripts): add /g flag to regex replacements in update-readme.ts Add global flag to 6 skill-count replacement regexes to prevent stale matches if duplicate patterns appear in the future Ultraworked with Sisyphus (https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- scripts/update-readme.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/update-readme.ts b/scripts/update-readme.ts index 66ede3c..11d1bfb 100644 --- a/scripts/update-readme.ts +++ b/scripts/update-readme.ts @@ -251,27 +251,27 @@ function updateReadme() { // Sync all hardcoded skill counts updatedContent = updatedContent.replace( - /\d+\+pre-built\+AI\+Agent\+Skills/, + /\d+\+pre-built\+AI\+Agent\+Skills/g, `${skills.length}+pre-built+AI+Agent+Skills` ); updatedContent = updatedContent.replace( - /\/badge\/skills-\d+-blue/, + /\/badge\/skills-\d+-blue/g, `/badge/skills-${skills.length}-blue` ); updatedContent = updatedContent.replace( - /Explore our growing library of \d+ specialized skills/, + /Explore our growing library of \d+ specialized skills/g, `Explore our growing library of ${skills.length} specialized skills` ); updatedContent = updatedContent.replace( - /\d+ skills across GTM/, + /\d+ skills across GTM/g, `${skills.length} skills across GTM` ); updatedContent = updatedContent.replace( - /lines=\d+\+Agent\+Skills/, + /lines=\d+\+Agent\+Skills/g, `lines=${skills.length}+Agent+Skills` ); updatedContent = updatedContent.replace( - /\d+ specialized skills across GTM/, + /\d+ specialized skills across GTM/g, `${skills.length} specialized skills across GTM` );
Give this skill a competitor's App Store or Google Play URL. It collects their public low-star reviews, detects where their store description's claims break against real complaints, and outputs a one-session brief: ranked complaint clusters, a broken promise map, landing page headline variants, and ad copy you can use tomorrow. 1.0.0
company-radarCompetitive intelligence orchestrator for opendirectory. Takes company names, researches them across 8+ platforms in parallel, computes a 0-100 heat score, and outputs structured radar reports with AI briefings.1.0.0
competitor-pr-finder Give it your product URL. It finds your top 5 competitors, researches every press mention, podcast appearance, and community post across all of them, and tells you exactly which channels to pitch -- with the journalist's name, the angle that got your competitors featured, and a ready-to-send cold pitch for your product.