Communitygithub.com

X AI 热点雷达

Erkennt neue KI-Tools und -Keywords, bevor sie viral gehen, und sichert sich Domain- und Traffic-Vorteile durch frühzeitiges Handeln.

Was ist X AI 热点雷达?

Der „X AI Hotspot Radar“ ist eine KI-gestützte Agentenfertigkeit, die gezielt nach viralen KI-Tools und -Keywords auf X (Twitter) sucht, noch bevor sie die breite Masse erreichen. Er nutzt eine mehrschichtige Suchmatrix (L0 bis L4), um wilde Viraltrends, neue Produktlaunches, GitHub-Explosionen und FOMO-Signale zu erfassen. Die gesammelten Beiträge werden mit einem Hotness-Score bewertet, der Likes, Wachstumsgeschwindigkeit und vor allem die Projektfrische (Alter des GitHub-Repos) berücksichtigt – um sicherzustellen, dass nur wirklich neue, chancenreiche Projekte in den Top-10-Report aufgenommen werden. Die Fertigkeit unterstützt die Browserautomatisierung (Cookie-Injektion für X) und Feishu-Benachrichtigungen und eignet sich besonders für Entwickler und Arbitrage-Händler, die frühzeitig Domain-Namen sichern und Nischenseiten aufbauen möchten.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/kennyzir/7deer_skills/tree/HEAD/x-demand-radar

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht X AI 热点雷达?

Kernmetrik

Endbewertung = X-Hitze × Projektfrische

  • raw_hot_score = likes × log(1 + likes_per_hour)
  • Wachstumsrate = Likes / (aktuelle Zeit – Veröffentlichungszeit) in Stunden
  • Projektfrische-Prüfung: Nach Erkennung eines GitHub-Projekts muss zur Repository-Seite navigiert werden, um das Erstellungsdatum zu überprüfen.
  • final_score = raw_hot_score × freshness_multiplier
    • Projekt < 7 Tage: × 1.0
    • Projekt 7–30 Tage: × 0.7
    • Projekt 30–90 Tage: × 0.3
    • Projekt > 90 Tage: markiert als ⚠️ altes Projekt, nicht im Ranking

🔴 Wichtige Lektion: UI-TARS-desktop (bytedance) hat 29k Sterne, aber das Repo existiert seit Monaten. Der X-Post ist zwar neu, das Projekt aber nicht → Arbitrage-Fenster geschlossen. Hohe Hitze ≠ neues Projekt.

Suchmatrix (6 Detektor-Schichten)

Jede Schicht hat ein anderes Ziel und deckt die gesamte Kette ab: wilde Hotspots → neue Produkte → virale Verbreitung → Open-Source-Explosion → FOMO-Bedarf.

L0: Wilde Viren (48h-Fenster) 🆕

Erfasst Produkte/Spiele/Tools, die ohne KI-Tag viral gehen. Dies ist die entscheidende Schicht für H5-Spiele, Web-Tools und andere nicht-KI-Hotspots.

("this is insane" OR "game changer" OR "holy shit" OR "mind blown" OR "this is crazy" OR "cannot believe" OR "blown away") (game OR tool OR app OR website OR "web app" OR builder OR generator OR platform OR "waitlist") min_faves:200 since:SINCE_48H

⚠️ Hinweis: L0 erfordert kein KI-Keyword, min_faves auf 200 erhöht, um Rauschen zu filtern.

L1: Neue Produkteinführungen – KI (24h-Fenster)

Erfasst KI-Tools, die gerade „gestartet/Open-Source“ wurden – das früheste Signal.

("just launched" OR "just dropped" OR "just shipped" OR "new AI tool" OR "just released" OR "introducing" OR "launching today") (AI OR LLM OR GPT OR agent OR open source) min_faves:30 since:SINCE_24H

L1-b: Allgemeine neue Produkteinführungen (24h-Fenster) 🆕

Erfasst neue nicht-KI-Produkte/Spiele/Tools.

("just launched" OR "just dropped" OR "just shipped" OR "just released" OR "introducing" OR "launching today" OR "new" OR "announcing") (game OR tool OR app OR website OR "web app" OR builder OR platform) min_faves:100 since:SINCE_24H

L2: Virale Verbreitung (48h-Fenster)

Erfasst KI-Produkte, die gerade massiv geteilt werden.

("this is insane" OR "game changer" OR "holy shit" OR "mind blown" OR "this is crazy" OR "cannot believe" OR "blown away") (AI OR LLM OR GPT OR agent OR tool) min_faves:100 since:SINCE_48H

L3: GitHub-Sterne explodieren (48h-Fenster)

Open-Source-KI-Projekte, die plötzlich viral gehen.

("github.com" OR "open source") (AI OR LLM OR GPT OR agent) ("stars" OR "trending" OR "blew up" OR "blowing up" OR "just hit") min_faves:100 since:SINCE_48H

L4: FOMO / Warteliste (72h-Fenster)

„Kann nicht warten“, „Einladung anfordern“, „lange Schlange“ = Signal für überlaufende Nachfrage.

("waitlist" OR "beta access" OR "invite" OR "early access" OR "can't wait" OR "need this") (AI OR LLM OR tool OR app) min_faves:50 since:SINCE_72H

Ausführungsablauf

[Cron: alle 12 Stunden]
       ↓
[Browser-Cookie für X injizieren → eingeloggter Zustand]
       ↓
[L0-L4 schichtweise suchen → JS-Scrolling sammeln]
       ↓
[Zusammenführen und deduplizieren → raw_hot_score berechnen]
       ↓
[🔍 Schritt 2.5: Projektfrische prüfen]
       ↓
[KI-Extraktion: Keyword + Produktname + Projektalter + Zusammenfassung]
       ↓
[Top 10 sortieren → Bericht generieren]
       ↓
[Direkt an Feishu senden]

Schritt 1: Such-URL konstruieren

const now = new Date();
const since24h = new Date(now - 24*60*60*1000).toISOString().split('T')[0];
const since48h = new Date(now - 48*60*60*1000).toISOString().split('T')[0];
const since72h = new Date(now - 72*60*60*1000).toISOString().split('T')[0];

const SEARCH_GROUPS = [
  {
    layer: 'L0-Wilde Viren',
    q: `("this is insane" OR "game changer" OR "holy shit" OR "mind blown" OR "this is crazy" OR "cannot believe" OR "blown away") (game OR tool OR app OR website OR "web app" OR builder OR generator OR platform OR "waitlist") min_faves:200 since:${since48h}`,
    since: since48h
  },
  {
    layer: 'L1-Neue Produkte-KI',
    q: `("just launched" OR "just dropped" OR "just shipped" OR "new AI tool" OR "just released" OR "introducing") (AI OR LLM OR GPT OR agent OR "open source") min_faves:30 since:${since24h}`,
    since: since24h
  },
  {
    layer: 'L1-b-Allgemeine Neue',
    q: `("just launched" OR "just dropped" OR "just shipped" OR "just released" OR "introducing" OR "launching today" OR "new" OR "announcing") (game OR tool OR app OR website OR "web app" OR builder OR platform) min_faves:100 since:${since24h}`,
    since: since24h
  },
  {
    layer: 'L2-Virale Verbreitung',
    q: `("this is insane" OR "game changer" OR "holy shit" OR "mind blown" OR "this is crazy" OR "cannot believe" OR "blown away") (AI OR LLM OR GPT OR agent OR tool) min_faves:100 since:${since48h}`,
    since: since48h
  },
  {
    layer: 'L3-GitHub-Explosion',
    q: `("github.com" OR "open source") (AI OR LLM OR GPT OR agent) ("stars" OR "trending" OR "blew up" OR "blowing up" OR "just hit") min_faves:100 since:${since48h}`,
    since: since48h
  },
  {
    layer: 'L4-FOMO',
    q: `("waitlist" OR "beta access" OR "invite" OR "early access" OR "can't wait" OR "need this") (AI OR LLM OR tool OR app) min_faves:50 since:${since72h}`,
    since: since72h
  }
];

Schritt 2: Sammeln + Hitzewert berechnen

// In der Browser-Konsole ausführen
async function collectAndScore(sinceHours) {
  let allPosts = [];
  let prevCount = 0;
  let scrolls = 0;
  const maxScrolls = 12;

  while (scrolls < maxScrolls) {
    const articles = document.querySelectorAll('article');
    articles.forEach((a) => {
      const textEl = a.querySelector('[data-testid="tweetText"]') || a.querySelector('[lang]');
      const text = textEl?.innerText || '';
      if (!text || text.length < 30) return;

      const likesEl = a.querySelector('[data-testid="like"] span');
      let likes = 0;
      if (likesEl) {
        const txt = likesEl.innerText.replace(/,/g, '');
        if (txt.includes('K')) likes = Math.round(parseFloat(txt.replace('K','')) * 1000);
        else if (txt.includes('M')) likes = Math.round(parseFloat(txt.replace('M','')) * 1000000);
        else likes = parseInt(txt) || 0;
      }

      // Autor extrahieren
      const allLinks = Array.from(a.querySelectorAll('a[role="link"]'));
      const authorLink = allLinks.find(l => l.href && l.href.includes('x.com/') && !l.href.includes('/status/') && !l.href.includes('search') && !l.href.includes('hashtag'));
      const author = authorLink?.href?.split('/').pop() || '';

      // Zeit extrahieren
      const timeEl = a.querySelector('time');
      const time = timeEl?.getAttribute('datetime') || '';

      // Link extrahieren
      const statusLink = allLinks.find(l => l.href && l.href.includes('/status/'));
      const link = statusLink?.href || '';

      // Reposts extrahieren
      const repostEl = a.querySelector('[data-testid="retweet"] span, [data-testid="repost"] span');
      let reposts = 0;
      if (repostEl) {
        const txt = repostEl.innerText.replace(/,/g, '');
        if (txt.includes('K')) reposts = Math.round(parseFloat(txt.replace('K','')) * 1000);
        else reposts = parseInt(txt) || 0;
      }

      if (!allPosts.some(p => p.text === text)) {
        allPosts.push({ text: text.substring(0, 400), likes, reposts, author, time, link });
      }
    });

    if (allPosts.length === prevCount && scrolls > 2) break;
    prevCount = allPosts.length;

    window.scrollBy(0, 600);
    await new Promise(r => setTimeout(r, 1500));
    scrolls++;
  }

  // Hitzewert berechnen
  const now = new Date();
  return allPosts.map(p => {
    const postTime = new Date(p.time);
    const hoursAgo = Math.max(0.1, (now - postTime) / (1000 * 60 * 60));
    const likesPerHour = p.likes / hoursAgo;
    const hotScore = Math.round(p.likes * Math.log(1 + likesPerHour));
    return { ...p, hoursAgo: Math.round(hoursAgo * 10) / 10, likesPerHour: Math.round(likesPerHour), hotScore };
  }).sort((a, b) => b.hotScore - a.hotScore);
}

Schritt 2.5: Projektfrische-Prüfung (🔴 Muss ausgeführt werden)

⚠️ X-Hitze ≠ neues Projekt. Ein altes Projekt, das erneut erwähnt wird, kann auf X heiß sein, aber das Arbitrage-Fenster ist geschlossen.

Zuerst die bekannte Liste alter Projekte prüfen: references/known-stale-repos.md – Treffer direkt ausschließen, ohne zu GitHub zu navigieren.

Für jedes Signal, das einen GitHub-Link enthält, muss zur Repository-Seite navigiert werden, um das Erstellungsdatum zu überprüfen:

// Auf der GitHub-Repository-Seite ausführen
const createdEl = document.querySelector('relative-time');
const createdAt = createdEl?.getAttribute('datetime') || '';
const daysSinceCreated = (new Date() - new Date(createdAt)) / (1000 * 60 * 60 * 24);

let freshnessLabel;
if (daysSinceCreated < 7) freshnessLabel = '🆕 Neues Produkt';
else if (daysSinceCreated < 30) freshnessLabel = '📈 Im Aufstieg';
else if (daysSinceCreated < 90) freshnessLabel = '⚠️ Altes Projekt wiederbelebt';
else freshnessLabel = '💀 Antiquität (ausschließen)';

const freshnessMultiplier = daysSinceCreated < 7 ? 1.0 : daysSinceCreated < 30 ? 0.7 : daysSinceCreated < 90 ? 0.3 : 0;
const finalScore = Math.round(rawHotScore * freshnessMultiplier);

Filterregel: Projekte mit freshnessMultiplier === 0 direkt ausschließen, nicht im Bericht aufführen.

Bei Nicht-GitHub-Projekten (z. B. neue Produkteinführungen, APIs, Wartelisten) wird standardmäßig freshnessMultiplier = 0.8 verwendet (etwas Toleranz für nicht-Open-Source-Projekte); wenn jedoch ein Veröffentlichungsdatum von der Seite extrahiert werden kann, wird das tatsächliche Datum bevorzugt.

Schritt 3: Filterregeln

// Auszuschließende Themen: Crypto, Krieg, NSFW, Meme-Coin
const excludePatterns = [
  /crypto|bitcoin|nft|token.*sale/i,
  /war|killed|attack|bomb/i,
  /nsfw|onlyfans|porn/i,
  /ai.*girlfriend|ai.*waifu/i,
  /meme.*coin/i
];

const filtered = allPosts
  .filter(p => p.hotScore >= 200)  // Hitzewert-Schwellwert
  .filter(p => !excludePatterns.some(r => r.test(p.text)))
  .slice(0, 15);

Schritt 4: KI-Keyword-Extraktion

Für jeden Post folgenden Prompt ausführen:

Extrahiere die heißen Keywords aus folgendem X-Post (nicht nur KI):

Post: {{ text }}
Autor: @{{ author }}
Likes: {{ likes }} | Reposts: {{ reposts }}
Veröffentlicht: {{ hoursAgo }} Stunden her | Wachstumsrate: {{ likesPerHour }} Likes/Stunde

Ausgabe:
- **Keyword/Produktname**: [1–3 Kern-Keywords extrahieren]
- **Ein Satz**: [Was macht dieses Tool/Projekt?]
- **Hitzebewertung**: [hotScore]
- **Arbitrage-Signal**: Stark/Mittel/Schwach (Wachstumsrate > 500 Likes/h = Stark, 100–500 = Mittel, < 100 = Schwach)

Schritt 5: Ausgabeberichtsformat

JSON-Ausgabestruktur (demand-radar.json)

Jedes Signal muss alle folgenden Felder enthalten:

{
  "date": "YYYY-MM-DD",
  "signals": [{
    "rank": 1,
    "keyword": "Produkt/Projektname",
    "description": "Ein-Satz-Beschreibung, was es tut",
    "likes": 188, "velocity": 109, "hotScore": 884,
    "freshness": "🆕 Neues Produkt", "finalScore": 884, "signal": "🟡 Mittel",
    "author": "@handle",
    "tweetLink": "https://x.com/user/status/xxx",
    "hoursAgo": 1.7,
    "github": "owner/repo", "stars": "2.8K",
    "sourceLayer": "L1 Neue Produkte-KI",
    "arbitrageDirection": "Erklärung der Arbitrage-Richtung + empfohlene Domain",
    "domainSuggestions": ["domain1.com", "domain2.com"],
    "actionPlan": "Konkreter Aktionsplan: Was tun, wie, warum jetzt der richtige Zeitpunkt ist",
    "painPoint": "Schmerzpunkt des Benutzers: Warum jemand das braucht"
  }]
}

🔴 Wichtige Regel: Jedes Signal muss tweetLink (Original-Post-Link), arbitrageDirection (Arbitrage-Richtung), domainSuggestions (Domain-Vorschläge), actionPlan (Aktionsplan) und painPoint (Schmerzpunkt) enthalten. Signale, bei denen eines dieser Felder fehlt, gelten als unvollständig und erscheinen nicht im Bericht.

🔍 KI-Hotspot-Radar | {{DATE}} {{TIME}}

> **Datenquelle: X/Twitter-Echtzeit-Scraping @claw0x**

## 📰 Heutige News-Sidebar

| Thema | Zeit | Anzahl Posts |
|------|------|------|
| {{topic}} | {{age}} | {{posts}} |

## 🔥 Top 10 Hitze-Ranking

| # | Keyword | Likes | Wachstumsrate (Likes/h) | Hitzewert | Frische | Endbewertung | Arbitrage-Signal |
|---|--------|-----|-----------|--------|--------|---------|---------|
| 1 | xxx | 5.2K | 1.200 | 36.000 | 🆕 0.8 Tage | 36.000 | 🔴 Stark |

### 🚀 Sofort handeln (Arbitrage-Signal ≥ Mittel)
1. **{{keyword}}** — {{summary}}
   - @{{author}} | {{likes}} Likes | {{likesPerHour}} Likes/h | {{hoursAgo}}h her
   - GitHub: `{{owner/repo}}` | Erstellt vor {{daysAgo}} Tagen | {{stars}} Sterne
   - Domain: {{domain}}.com ({{status}})
   - Arbitrage-Richtung: {{arbitrageDirection}}

## ⚠️ Ausgeschlossen (alte Projekte wiederbelebt)

| Projekt | Grund | Sterne | Alter |
|------|------|------|------|
| UI-TARS-desktop (ByteDance) | Desktop-Automatisierungs-Agent, auf X wieder erwähnt | 30.9K | >12 Monate |

---

📊 Scan-Parameter
- Suchschichten: L0 Wild / L1 Neue KI / L1-b Allgemein Neu / L2 Viral / L3 GitHub / L4 FOMO
- Zeitraum: {{since}} – {{until}}
- Rohe Posts: {{raw}} → dedupliziert {{deduped}} → gefiltert {{filtered}} → ausgewählt {{top}}
- GitHub-Prüfung: {{excluded}} alte Projekte ausgeschlossen
- Browser-Status: Eingeloggt als @claw0x

## 🔮 Wichtige Erkenntnisse

(2–4 wichtige Trends aus dem heutigen Scan auflisten)

Schritt 6: Deployment (git push → CF Pages)

cd /Volumes/sunzi/Code/ludusAI
# Täglichen JSON-Snapshot für /radar-Detailseiten speichern
cp public/data/demand-radar.json "public/data/radar/YYYY-MM-DD.json" 2>/dev/null || true
# Manifest erstellen
ls public/data/radar/*.json | python3 -c "
import json,os,sys
m=[]
for f in sys.stdin.read().strip().split():
  d=json.load(open(f))
  t=d.get('top10',[])
  m.append({'date':os.path.basename(f).replace('.json',''),'topKeywords':[x.get('keyword','') for x in t[:3]],'signalCount':len(t),'newsTopics':[n.get('topic','') for n in d.get('news',[])[:2]],'insights':d.get('insights',[])[:3],'strongSignal':sum(1 for x in t if 'Stark' in x.get('signal','')),'mediumSignal':sum(1 for x in t if 'Mittel' in x.get('signal','')),'raw':d.get('scanParams',{}).get('raw',0),'top':d.get('scanParams',{}).get('top',0),'excluded':d.get('scanParams',{}).get('githubExcluded',0),'layers':d.get('scanParams',{}).get('layers',[])})
m.sort(key=lambda x:x['date'],reverse=True)
json.dump(m,open('public/data/radar-manifest.json','w'),ensure_ascii=False,indent=2)
print(f'manifest: {len(m)} reports')
"
git add daily-reports/YYYY-MM-DD/x-demand-radar.md public/data/demand-radar.json public/data/radar/YYYY-MM-DD.json public/data/radar-manifest.json
git commit -m "radar: YYYY-MM-DD HH:MM CST - <top signal summary>"
git pull --rebase && git push  # ⚠️ Muss rebase sein, um non-fast-forward Ablehnung zu vermeiden

⚠️ Muss mit send_message an Feishu gesendet werden, nicht auf Cron-Announcement verlassen.

Cookie-Injektion (vor jeder Ausführung)

⚠️ Siehe references/x-auth-and-collection.md – enthält den vollständigen Injektionsablauf, async-IIFE-Vorlage, K/M-Parsing, hotScore-Formel.

// Zuerst zu x.com navigieren, dann injizieren, dann Anmeldung auf x.com/home bestätigen
document.cookie = "auth_token=06dec19f563932f39d96f93e9d8c005d3de9b7a9; domain=.x.com; path=/; secure; SameSite=None";

Konfiguration

  • X-Konto: @claw0x (eingeloggter Browser)
  • Ausführungshäufigkeit: Alle 12 Stunden (9:00 + 21:00 CST)
  • Cookie-Gültigkeit: Muss vom Benutzer regelmäßig aktualisiert werden (auth_token)
  • Ausgabeziele: daily-reports/YYYY-MM-DD/x-demand-radar.md + public/data/demand-radar.json
  • Deployment: git push → CF Pages automatischer Build

Fallstricke

  1. Cookie nicht über Sitzungen hinweg persistent: Jeder Start von Hermes ist eine neue Browser-Instanz, das Cookie muss jedes Mal neu injiziert werden. Der erste Schritt jeder Cron-Ausführung ist Cookie-Injektion → Anmeldung bestätigen.
  2. browser_console kann nicht direkt return verwenden: Muss in ein IIFE (async function() { ... })() verpackt werden, sonst Fehler Illegal return statement. Siehe references/x-auth-and-collection.md.
  3. Suchergebnisse-Sparsity ist normal: Bei min_faves≥100 + komplexen booleschen Abfragen sind 4–16 Ergebnisse pro Schicht normal. L3 (GitHub) ist besonders spärlich. min_faves-Schwellwert nicht senken, sonst überdeckt Rauschen das Signal.
  4. Today's News-Sidebar ist eine kostenlose Signalquelle: Die rechte Seite jeder Suchseite zeigt aktuelle News-Themen und Post-Anzahlen. Dies sind definitive Hotspots und sollten in den Bericht aufgenommen werden.
  5. Push muss direkt an Feishu gesendet werden: Nicht auf Cron-Announcement verlassen. Nachdem die Ergebnisse in Dateien geschrieben wurden, sofort mit einer Nachricht senden.
  6. Suchbegriffe sind global: Alle Abfragen auf Englisch, keine Regionseinschränkung. Bericht fokussiert auf globale Hotspots (nicht nur KI).
  7. execute_code unterstützt keine großen Inline-JSON-Strings: Das Einbetten von JSON-Daten direkt in einen Python-String führt zu SyntaxError: leading zeros oder ähnlichen Parsing-Fehlern. Korrekt: Mit write_file eine temporäre Datei schreiben, dann mit open() lesen: with open('/tmp/data.json') as f: data = json.load(f). Ebenso gibt read_file Text mit Zeilennummern-Präfix zurück (z. B. 1|{...}), nicht direkt json.loads()-fähig – natives open() verwenden.
  8. git push kann abgelehnt werden (non-fast-forward): Das Remote-Repository könnte andere Cron-Instanzen oder manuelle Commits enthalten, die vor dem aktuellen Push liegen. Immer git pull --rebase && git push, niemals allein git push.
  9. JS-gesammelte abgeschnittene Post-Texte können GitHub-URLs verlieren: text.substring(0, 300) könnte den GitHub-Link am Ende abschneiden. Wenn ein Post GitHub erwähnt, aber kein github.com-Link extrahiert wurde, muss zum Original-Post navigiert (browser_navigate zum link-Feld) und die vollständige URL extrahiert werden, oder mit der GitHub-Suche nach dem Repo-Name-Keyword gesucht werden.
  10. L0-Schicht hat starkes Rauschen (bestätigt): min_faves:200 stoppt nicht viele umgangssprachliche „game changer“-Posts (politisch/sportlich/alltäglich). Beim ersten L0-Lauf waren nur 4 von 19 Posts potenziell produktrelevant. Empfehlung: Wenn das Signal/Rausch-Verhältnis von L0 zwei Radarläufe hintereinander unter 20 % liegt, min_faves auf 500 erhöhen oder Ausschlusswörter wie -(political OR sports OR religion) in die L0-Abfrage aufnehmen.

Zusätzliche Signalquellen (optional)

Verwandte Skills