💬 Prompts

GitHubTrends

--- name: GitHubTrends description: 显示GitHub热门项目趋势,生成可视化仪表板。USE WHEN github trends, trending projects, hot repositories, popular github projects, generate dashboard

❤️ 0
⬇️ 0
👁 2
Share

Description


name: GitHubTrends description: 显示GitHub热门项目趋势,生成可视化仪表板。USE WHEN github trends, trending projects, hot repositories, popular github projects, generate dashboard, create webpage. version: 2.0.0

Customization

Before executing, check for user customizations at: ~/.claude/skills/CORE/USER/SKILLCUSTOMIZATIONS/GitHubTrends/

If this directory exists, load and apply any PREFERENCES.md, configurations, or resources found there. These override default behavior. If the directory does not exist, proceed with skill defaults.

GitHubTrends - GitHub热门项目趋势

快速发现GitHub上最受欢迎的开源项目。


Philosophy

GitHub trending是发现优质开源项目的最佳途径。这个skill让老王我能快速获取当前最热门的项目列表,按时间周期(每日/每周)和编程语言筛选,帮助发现值得学习和贡献的项目。


Quick Start

# 查看本周最热门的项目(默认)
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly

# 查看今日最热门的项目
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts daily

# 按语言筛选
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --language=TypeScript
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --language=Python

# 指定显示数量
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --limit=20

When to Use This Skill

Core Triggers - Use this skill when user says:

Direct Requests

  • "show github trends" 或 "github trending"
  • "显示热门项目" 或 "看看有什么热门项目"
  • "what's trending on github" 或 "github hot projects"
  • "本周热门项目" 或 "weekly trending"
  • "今日热门项目" 或 "daily trending"

Discovery Requests

  • "discover popular projects" 或 "发现热门项目"
  • "show repositories trending" 或 "显示trending仓库"
  • "github上什么最火" 或 "what's hot on github"
  • "找点好项目看看" 或 "find good projects"

Language-Specific

  • "TypeScript trending projects" 或 "TypeScript热门项目"
  • "Python trending" 或 "Python热门项目"
  • "show trending Rust projects" 或 "显示Rust热门项目"
  • "Go语言热门项目" 或 "trending Go projects"

Dashboard & Visualization

  • "生成 GitHub trending 仪表板" 或 "generate trending dashboard"
  • "创建趋势网页" 或 "create trending webpage"
  • "生成交互式报告" 或 "generate interactive report"
  • "export trending dashboard" 或 "导出仪表板"
  • "可视化 GitHub 趋势" 或 "visualize github trends"

Core Capabilities

获取趋势列表

  • 每日趋势 - 过去24小时最热门项目
  • 每周趋势 - 过去7天最热门项目(默认)
  • 语言筛选 - 按编程语言过滤(TypeScript, Python, Go, Rust等)
  • 自定义数量 - 指定返回项目数量(默认10个)

生成可视化仪表板 🆕

  • 交互式HTML - 生成交互式网页仪表板
  • 数据可视化 - 语言分布饼图、Stars增长柱状图
  • 技术新闻 - 集成 Hacker News 技术资讯
  • 实时筛选 - 按语言筛选、排序、搜索功能
  • 响应式设计 - 支持桌面、平板、手机

项目信息

  • 项目名称和描述
  • Star数量和变化
  • 编程语言
  • 项目URL

Tool Usage

GetTrending.ts

Location: Tools/GetTrending.ts

功能: 从GitHub获取trending项目列表

参数:

  • period - 时间周期:dailyweekly(默认:weekly)
  • --language - 编程语言筛选(可选)
  • --limit - 返回项目数量(默认:10)

使用示例:

# 基本用法
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly

# 带参数
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --language=TypeScript --limit=15

# 简写
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts daily -l=Python

实现方式: 使用 GitHub官方trending页面:https://github.com/trending 通过 fetch API 读取页面内容并解析


GenerateDashboard.ts 🆕

Location: Tools/GenerateDashboard.ts

功能: 生成交互式数据可视化仪表板HTML文件

参数:

  • --period - 时间周期:dailyweekly(默认:weekly)
  • --language - 编程语言筛选(可选)
  • --limit - 返回项目数量(默认:10)
  • --include-news - 包含技术新闻
  • --news-count - 新闻数量(默认:10)
  • --output - 输出文件路径(默认:./github-trends.html)

使用示例:

# 基本用法 - 生成本周仪表板
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts

# 包含技术新闻
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts --include-news

# TypeScript 项目每日仪表板
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts \
  --period daily \
  --language TypeScript \
  --limit 20 \
  --include-news \
  --output ~/ts-daily.html

实现方式:

  • 获取 GitHub trending 项目数据
  • 获取 Hacker News 技术新闻
  • 使用 Handlebars 模板引擎渲染 HTML
  • 集成 Tailwind CSS 和 Chart.js
  • 生成完全独立的 HTML 文件(通过 CDN 加载依赖)

Output Format

# GitHub Trending Projects - Weekly (2025-01-19)

## 1. vercel/next.js - ⭐ 125,342 (+1,234 this week)
**Language:** TypeScript
**Description:** The React Framework for the Web
**URL:** https://github.com/vercel/next.js

## 2. microsoft/vscode - ⭐ 160,890 (+987 this week)
**Language:** TypeScript
**Description:** Visual Studio Code
**URL:** https://github.com/microsoft/vscode

...

---
📊 Total: 10 projects | Language: All | Period: Weekly

Supported Languages

常用编程语言筛选:

  • TypeScript - TypeScript项目
  • JavaScript - JavaScript项目
  • Python - Python项目
  • Go - Go语言项目
  • Rust - Rust项目
  • Java - Java项目
  • C++ - C++项目
  • Ruby - Ruby项目
  • Swift - Swift项目
  • Kotlin - Kotlin项目

Workflow Integration

这个skill可以被其他skill调用:

  • OSINT - 在调查技术栈时发现热门工具
  • Research - 研究特定语言生态系统的趋势
  • System - 发现有用的PAI相关项目

Technical Notes

数据来源: GitHub官方trending页面 更新频率: 每小时更新一次 无需认证: 使用公开页面,无需GitHub API token 解析方式: 通过HTML解析提取项目信息

错误处理:

  • 网络错误会显示友好提示
  • 解析失败会返回原始HTML供调试
  • 支持的语言参数不区分大小写

Future Enhancements

可能的未来功能:

  • 支持月度趋势(如果GitHub提供)
  • 按stars范围筛选(1k+, 10k+, 100k+)
  • 保存历史数据用于趋势分析
  • 集成到其他skill的自动化工作流

Voice Notification

When executing a workflow, do BOTH:

  1. Send voice notification:

    curl -s -X POST http://localhost:8888/notify \
      -H "Content-Type: application/json" \
      -d '{"message": "Running the GitHubTrends workflow"}' \
      > /dev/null 2>&1 &
    
  2. Output text notification:

    Running the **GitHubTrends** workflow...
    

Full documentation: ~/.claude/skills/CORE/SkillNotifications.md FILE:README.md

GitHubTrends Skill

快速发现GitHub上最受欢迎的开源项目,生成可视化仪表板!

功能特性

基础功能

  • ✅ 获取每日/每周热门项目列表
  • ✅ 按编程语言筛选(TypeScript, Python, Go, Rust等)
  • ✅ 自定义返回项目数量
  • ✅ 显示Star总数和周期增长
  • ✅ 无需GitHub API token

可视化仪表板 🆕

  • 交互式HTML - 生成交互式网页仪表板
  • 📊 数据可视化 - 语言分布饼图、Stars增长柱状图
  • 📰 技术新闻 - 集成 Hacker News 最新资讯
  • 🔍 实时筛选 - 按语言筛选、排序、搜索
  • 📱 响应式设计 - 支持桌面、平板、手机
  • 🎨 美观界面 - Tailwind CSS + GitHub 风格

快速开始

查看本周热门项目(默认)

bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly

查看今日热门项目

bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts daily

按语言筛选

# TypeScript热门项目
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --language=TypeScript

# Python热门项目
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --language=Python

# Go热门项目
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly -l=Go

指定返回数量

# 返回20个项目
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --limit=20

# 组合使用:返回15个TypeScript项目
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --language=TypeScript --limit=15

生成可视化仪表板 🆕

基本用法

# 生成本周趋势仪表板(默认)
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts

包含技术新闻

# 生成包含 Hacker News 的仪表板
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts --include-news

高级选项

# 生成 TypeScript 项目每日仪表板,包含 15 条新闻
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts \
  --period daily \
  --language TypeScript \
  --limit 20 \
  --include-news \
  --news-count 15 \
  --output ~/Downloads/ts-daily-trends.html

仪表板功能

生成的 HTML 文件包含:

  • 统计概览 - 总项目数、总 stars、top 项目
  • 语言分布图 - 饼图展示各语言占比
  • Stars 增长图 - 柱状图展示增长趋势
  • 项目卡片 - 美观的卡片式项目展示
  • 技术新闻 - Hacker News 最新资讯
  • 交互功能 - 筛选、排序、搜索
  • 响应式 - 自适应各种屏幕尺寸

输出示例

# GitHub Trending Projects - Weekly (2026-01-19)

📊 **Total:** 10 projects | **Language:** All | **Period:** Weekly

---

## 1. vercel/next.js - ⭐ 125,342 (+1,234 this week)
**Language:** TypeScript
**Description:** The React Framework for the Web
**URL:** https://github.com/vercel/next.js

## 2. microsoft/vscode - ⭐ 160,890 (+987 this week)
**Language:** TypeScript
**Description:** Visual Studio Code
**URL:** https://github.com/microsoft/vscode

...

参数说明

参数 说明 默认值 可选值
period 时间周期 weekly daily, weekly
--language 编程语言筛选 全部 TypeScript, Python, Go, Rust, Java等
--limit 返回项目数量 10 任意正整数

支持的语言

常用的编程语言都可以作为筛选条件:

  • TypeScript - TypeScript项目
  • JavaScript - JavaScript项目
  • Python - Python项目
  • Go - Go语言项目
  • Rust - Rust项目
  • Java - Java项目
  • C++ - C++项目
  • Ruby - Ruby项目
  • Swift - Swift项目
  • Kotlin - Kotlin项目

Skill 触发词

当你说以下任何内容时,这个skill会被触发:

  • "show github trends" / "github trending"
  • "显示热门项目" / "看看有什么热门项目"
  • "weekly trending" / "本周热门项目"
  • "daily trending" / "今日热门项目"
  • "TypeScript trending" / "Python trending"
  • "what's hot on github" / "github上什么最火"

技术实现

  • 数据源: GitHub官方trending页面 (https://github.com/trending)
  • 解析方式: HTML解析提取项目信息
  • 认证: 无需GitHub API token
  • 更新频率: 每小时更新一次

目录结构

~/.claude/skills/GitHubTrends/
├── SKILL.md              # Skill主文件
├── README.md             # 使用文档(本文件)
├── Tools/
│   └── GetTrending.ts    # 获取trending数据的工具
└── Workflows/
    └── GetTrending.md    # 工作流文档

注意事项

  1. 网络要求: 需要能访问GitHub官网
  2. 更新频率: 数据每小时更新,不是实时
  3. 解析准确性: GitHub页面结构变化可能影响解析,如遇问题请检查 /tmp/github-trending-debug-*.html
  4. 语言参数: 不区分大小写,--language=typescript--language=TypeScript 效果相同

已知问题

  • GitHub trending页面的HTML结构复杂,某些项目的URL和名称可能解析不完整
  • 如果GitHub页面结构变化,工具可能需要更新解析逻辑

未来改进

  • 支持保存历史数据用于趋势分析
  • 按stars范围筛选(1k+, 10k+, 100k+)
  • 更智能的HTML解析(使用HTML解析库而非正则)
  • 集成到其他skill的自动化工作流

贡献

如果发现问题或有改进建议,欢迎提出!


Made with ❤️ by 老王 FILE:Tools/GetTrending.ts #!/usr/bin/env bun /**

  • GitHub Trending Projects Fetcher
  • 从GitHub获取trending项目列表
  • 支持每日/每周趋势,按语言筛选 */

import { $ } from "bun";

interface TrendingProject { rank: number; name: string; description: string; language: string; stars: string; starsThisPeriod: string; url: string; }

interface TrendingOptions { period: "daily" | "weekly"; language?: string; limit: number; }

function buildTrendingUrl(options: TrendingOptions): string { const baseUrl = "https://github.com/trending"; const since = options.period === "daily" ? "daily" : "weekly"; let url = ${baseUrl}?since=${since}; if (options.language) { url += &language=${encodeURIComponent(options.language.toLowerCase())}; } return url; }

function parseTrendingProjects(html: string, limit: number): TrendingProject[] { const projects: TrendingProject[] = []; try { const articleRegex = /<article[^>]>([\s\S]?)</article>/g; const articles = html.match(articleRegex) || []; const articlesToProcess = articles.slice(0, limit); articlesToProcess.forEach((article, index) => { try { const headingMatch = article.match(/<h[12][^>]>([\s\S]?)</h[12]>/); let repoName: string | null = null; if (headingMatch) { const headingContent = headingMatch[1]; const validLinkMatch = headingContent.match( /<a[^>]href="/([^/"/]+/[^/"/]+)"[^>]>(?![^<]login)/ ); if (validLinkMatch) { repoName = validLinkMatch[1]; } } if (!repoName) { const repoMatch = article.match( /<a[^>]href="/([a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+)"[^>]>(?!.(?:login|stargazers|forks|issues))/ ); repoName = repoMatch ? repoMatch[1] : null; } const descMatch = article.match(/<p[^>]class="[^"]col-9[^"]"[^>]>([\s\S]?)</p>/); const description = descMatch ? descMatch[1] .replace(/<[^>]+>/g, "") .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, '"') .trim() .substring(0, 200) : "No description"; const langMatch = article.match(/<span[^>]itemprop="programmingLanguage"[^>]>([^<]+)</span>/); const language = langMatch ? langMatch[1].trim() : "Unknown"; const starsMatch = article.match(/<a[^>]href="/[^"]+/stargazers"[^>]>(\d[\d,])\sstars?/); const totalStars = starsMatch ? starsMatch[1] : "0"; const starsAddedMatch = article.match(/(\d[\d,])\sstars?\s(?:today|this week)/i); const starsAdded = starsAddedMatch ? +${starsAddedMatch[1]} : ""; if (repoName && !repoName.includes("login") && !repoName.includes("return_to")) { projects.push({ rank: index + 1, name: repoName, description, language, stars: totalStars, starsThisPeriod: starsAdded, url: https://github.com/${repoName}, }); } } catch (error) { console.error(解析第${index + 1}个项目失败:, error); } }); } catch (error) { console.error("解析trending项目失败:", error); } return projects; }

function formatProjects(projects: TrendingProject[], options: TrendingOptions): string { if (projects.length === 0) { return "# GitHub Trending - No Projects Found\n\n没有找到trending项目,可能是网络问题或页面结构变化。"; } const periodLabel = options.period === "daily" ? "Daily" : "Weekly"; const languageLabel = options.language ? Language: ${options.language} : "Language: All"; const today = new Date().toISOString().split("T")[0]; let output = # GitHub Trending Projects - ${periodLabel} (${today})\n\n; output += 📊 **Total:** ${projects.length} projects | **${languageLabel}** | **Period:** ${periodLabel}\n\n; output += ---\n\n; projects.forEach((project) => { output += ## ${project.rank}. ${project.name} - ⭐ ${project.stars}; if (project.starsThisPeriod) { output += (${project.starsThisPeriod} this ${options.period}); } output += \n; output += **Language:** ${project.language}\n; output += **Description:** ${project.description}\n; output += **URL:** ${project.url}\n\n; }); output += ---\n; output += 📊 Data from: https://github.com/trending\n; return output; }

async function main() { const args = process.argv.slice(2); let period: "daily" | "weekly" = "weekly"; let language: string | undefined; let limit = 10; for (const arg of args) { if (arg === "daily" || arg === "weekly") { period = arg; } else if (arg.startsWith("--language=")) { language = arg.split("=")[1]; } else if (arg.startsWith("-l=")) { language = arg.split("=")[1]; } else if (arg.startsWith("--limit=")) { limit = parseInt(arg.split("=")[1]) || 10; } } const options: TrendingOptions = { period, language, limit }; try { const url = buildTrendingUrl(options); console.error(正在获取 GitHub trending 数据: ${url}); const response = await fetch(url); if (!response.ok) { throw new Error(HTTP ${response.status}: ${response.statusText}); } const html = await response.text(); const projects = parseTrendingProjects(html, limit); const formatted = formatProjects(projects, options); console.log(formatted); if (projects.length === 0) { const debugFile = /tmp/github-trending-debug-${Date.now()}.html; await Bun.write(debugFile, html); console.error(\n调试: 原始HTML已保存到 ${debugFile}); } } catch (error) { console.error("❌ 获取trending数据失败:"); console.error(error); process.exit(1); } }

main(); FILE:Workflows/GetTrending.md

GetTrending Workflow

获取GitHub trending项目列表的工作流程。

Description

这个工作流使用 GetTrending.ts 工具从GitHub获取当前最热门的项目列表,支持按时间周期(每日/每周)和编程语言筛选。

When to Use

当用户请求以下任何内容时使用此工作流:

  • "show github trends" / "github trending"
  • "显示热门项目" / "看看有什么热门项目"
  • "weekly trending" / "本周热门项目"
  • "daily trending" / "今日热门项目"
  • "TypeScript trending" / "Python trending" / 按语言筛选
  • "what's hot on github" / "github上什么最火"

Workflow Steps

Step 1: 确定参数

向用户确认或推断以下参数:

  • 时间周期: daily (每日) 或 weekly (每周,默认)
  • 编程语言: 可选(如 TypeScript, Python, Go, Rust等)
  • 项目数量: 默认10个

Step 2: 执行工具

运行 GetTrending.ts 工具:

# 基本用法(本周,全部语言,10个项目)
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly

# 指定语言
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --language=TypeScript

# 指定数量
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts weekly --limit=20

# 组合参数
bun ~/.claude/skills/GitHubTrends/Tools/GetTrending.ts daily --language=Python --limit=15

Step 3: 显示结果

工具会自动格式化输出,包括:

  • 项目排名
  • 项目名称
  • Star总数和周期内增长
  • 编程语言
  • 项目描述
  • GitHub URL

Step 4: 后续操作(可选)

根据用户需求,可以:

  • 打开某个项目页面
  • 使用其他skill进一步分析项目
  • 将结果保存到文件供后续参考

Integration with Other Skills

  • OSINT: 在调查技术栈时发现热门工具
  • Research: 研究特定语言生态系统的趋势
  • Browser: 打开项目页面进行详细分析

Notes

  • 数据每小时更新一次
  • 无需GitHub API token
  • 使用公开的GitHub trending页面
  • 支持的语言参数不区分大小写 FILE:Tools/GenerateDashboard.ts #!/usr/bin/env bun /**
  • GitHub Trending Dashboard Generator
  • 生成交互式数据可视化仪表板
  • 使用方式:
  • ./GenerateDashboard.ts [options]
  • 选项:
  • --period - daily | weekly (默认: weekly)
  • --language - 编程语言筛选 (可选)
  • --limit - 项目数量 (默认: 10)
  • --include-news - 包含技术新闻
  • --news-count - 新闻数量 (默认: 10)
  • --theme - light | dark | auto (默认: auto)
  • --output - 输出文件路径 (默认: ./github-trends.html)
  • 示例:
  • ./GenerateDashboard.ts
  • ./GenerateDashboard.ts --period daily --language TypeScript --include-news
  • ./GenerateDashboard.ts --limit 20 --output ~/trends.html */

import Handlebars from 'handlebars'; import type { DashboardOptions, TrendingProject, TechNewsItem, TemplateData } from './Lib/types'; import { registerHelpers, renderTemplate } from './Lib/template-helpers'; import { analyzeData } from './Lib/visualization-helpers';

// 注册 Handlebars 辅助函数 registerHelpers();

/**

  • 构建 GitHub trending URL */ function buildTrendingUrl(options: DashboardOptions): string { const baseUrl = "https://github.com/trending"; const since = options.period === "daily" ? "daily" : "weekly"; let url = ${baseUrl}?since=${since};

if (options.language) { url += &language=${encodeURIComponent(options.language.toLowerCase())}; }

return url; }

/**

  • 解析 HTML 提取 trending 项目
  • (从 GetTrending.ts 复制的逻辑) */ async function getTrendingProjects(options: DashboardOptions): Promise<TrendingProject[]> { const url = buildTrendingUrl(options);

console.error(正在获取 GitHub trending 数据: ${url});

const response = await fetch(url); if (!response.ok) { throw new Error(HTTP ${response.status}: ${response.statusText}); }

const html = await response.text(); return parseTrendingProjects(html, options.limit); }

/**

  • 解析 HTML */ function parseTrendingProjects(html: string, limit: number): TrendingProject[] { const projects: TrendingProject[] = [];

try { const articleRegex = /<article[^>]>([\s\S]?)</article>/g; const articles = html.match(articleRegex) || []; const articlesToProcess = articles.slice(0, limit);

articlesToProcess.forEach((article, index) => {
  try {
    const headingMatch = article.match(/<h[12][^>]*>([\s\S]*?)<\/h[12]>/);
    let repoName: string | null = null;

    if (headingMatch) {
      const headingContent = headingMatch[1];
      const validLinkMatch = headingContent.match(
        /<a[^>]*href="\/([^\/"\/]+\/[^\/"\/]+)"[^>]*>(?![^<]*login)/
      );
      if (validLinkMatch) {
        repoName = validLinkMatch[1];
      }
    }

    if (!repoName) {
      const repoMatch = article.match(
        /<a[^>]*href="\/([a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+)"[^>]*>(?!.*(?:login|stargazers|forks|issues))/
      );
      repoName = repoMatch ? repoMatch[1] : null;
    }

    const descMatch = article.match(/<p[^>]*class="[^"]*col-9[^"]*"[^>]*>([\s\S]*?)<\/p>/);
    const description = descMatch
      ? descMatch[1]
          .replace(/<[^>]+>/g, "")
          .replace(/&amp;/g, "&")
          .replace(/&lt;/g, "<")
          .replace(/&gt;/g, ">")
          .replace(/&quot;/g, '"')
          .trim()
          .substring(0, 200)
      : "No description";

    const langMatch = article.match(/<span[^>]*itemprop="programmingLanguage"[^>]*>([^<]+)<\/span>/);
    const language = langMatch ? langMatch[1].trim() : "Unknown";

    // 提取stars总数 - GitHub 改了 HTML 结构,数字在 SVG 后面
    const starsMatch = article.match(/stargazers[^>]*>[\s\S]*?<\/svg>\s*([\d,]+)/);
    const totalStars = starsMatch ? starsMatch[1] : "0";

    // 尝试提取新增stars - 格式:XXX stars today/this week
    const starsAddedMatch = article.match(/(\d[\d,]*)\s+stars?\s+(?:today|this week)/);
    const starsAdded = starsAddedMatch ? `+${starsAddedMatch[1]}` : "";

    if (repoName && !repoName.includes("login") && !repoName.includes("return_to")) {
      projects.push({
        rank: index + 1,
        name: repoName,
        description,
        language,
        stars: totalStars,
        starsThisPeriod: starsAdded,
        url: `https://github.com/${repoName}`,
      });
    }
  } catch (error) {
    console.error(`解析第${index + 1}个项目失败:`, error);
  }
});

} catch (error) { console.error("解析trending项目失败:", error); }

return projects; }

/**

  • 获取技术新闻 */ async function getTechNews(count: number): Promise<TechNewsItem[]> { const HN_API = 'https://hn.algolia.com/api/v1/search_by_date';

try { const response = await fetch(${HN_API}?tags=story&hitsPerPage=${count}); if (!response.ok) { throw new Error(HTTP ${response.status}: ${response.statusText}); }

const data = await response.json();

return data.hits.slice(0, count).map((hit: any) => ({
  id: hit.objectID,
  title: hit.title,
  url: hit.url || `https://news.ycombinator.com/item?id=${hit.objectID}`,
  source: 'hackernews',
  points: hit.points || 0,
  comments: hit.num_comments || 0,
  timestamp: new Date(hit.created_at).toISOString(),
  tags: hit._tags || []
}));

} catch (error) { console.error('获取 Hacker News 失败:', error); return []; } }

/**

  • 生成仪表板 */ async function generateDashboard(options: DashboardOptions): Promise { try { console.error('🚀 开始生成 GitHub Trending Dashboard...\n');

    // 1. 获取 GitHub Trending 数据 const projects = await getTrendingProjects(options); console.error(✅ 获取到 ${projects.length} 个项目);

    // 2. 获取技术新闻(如果启用) let news: TechNewsItem[] = []; if (options.includeNews) { news = await getTechNews(options.newsCount); console.error(✅ 获取到 ${news.length} 条新闻); }

    // 3. 分析数据 const analytics = analyzeData(projects); console.error(✅ 数据分析完成);

    // 4. 准备模板数据 const templateData: TemplateData = { title: 'GitHub Trending Dashboard', generatedAt: new Date().toLocaleString('zh-CN'), period: options.period === 'daily' ? 'Daily' : 'Weekly', projects, news, analytics, options };

    // 5. 渲染模板 const templatePath = ${import.meta.dir}/../Templates/dashboard.hbs; const templateContent = await Bun.file(templatePath).text(); const template = Handlebars.compile(templateContent); const html = template(templateData); console.error(✅ 模板渲染完成);

    // 6. 保存文件 await Bun.write(options.output, html); console.error(\n🎉 仪表板生成成功!); console.error(📄 文件路径: ${options.output}); console.error(\n💡 在浏览器中打开查看效果!);

} catch (error) { console.error('\n❌ 生成仪表板失败:'); console.error(error); process.exit(1); } }

/**

  • 解析命令行参数 */ function parseArgs(): DashboardOptions { const args = process.argv.slice(2);

const options: DashboardOptions = { period: 'weekly', limit: 10, output: './github-trends.html', includeNews: false, newsCount: 10, theme: 'auto' };

for (let i = 0; i < args.length; i++) { const arg = args[i];

switch (arg) {
  case '--period':
    options.period = args[++i] === 'daily' ? 'daily' : 'weekly';
    break;
  case '--language':
    options.language = args[++i];
    break;
  case '--limit':
    options.limit = parseInt(args[++i]) || 10;
    break;
  case '--include-news':
    options.includeNews = true;
    break;
  case '--news-count':
    options.newsCount = parseInt(args[++i]) || 10;
    break;
  case '--theme':
    options.theme = args[++i] === 'light' || args[++i] === 'dark' ? args[i] : 'auto';
    break;
  case '--output':
    options.output = args[++i];
    break;
  default:
    if (arg.startsWith('--output=')) {
      options.output = arg.split('=')[1];
    } else if (arg.startsWith('--language=')) {
      options.language = arg.split('=')[1];
    } else if (arg.startsWith('--limit=')) {
      options.limit = parseInt(arg.split('=')[1]) || 10;
    }
}

}

return options; }

/**

  • 主函数 */ async function main() { const options = parseArgs(); await generateDashboard(options); }

// 如果直接运行此脚本 if (import.meta.main) { main(); }

// 导出供其他模块使用 export { generateDashboard }; export type { DashboardOptions }; FILE:Tools/GetTechNews.ts #!/usr/bin/env bun /**

  • Tech News Fetcher
  • 从 Hacker News 和其他来源获取技术新闻
  • 使用方式:
  • ./GetTechNews.ts [count]
  • 参数:
  • count - 获取新闻数量 (默认: 10)
  • 示例:
  • ./GetTechNews.ts
  • ./GetTechNews.ts 20 */

import Parser from 'rss-parser'; import type { TechNewsItem } from './Lib/types';

const HN_API = 'https://hn.algolia.com/api/v1/search'; const parser = new Parser();

/**

  • 从 Hacker News Algolia API 获取新闻 */ async function getHackerNews(count: number): Promise<TechNewsItem[]> { try { const response = await fetch(${HN_API}?tags=front_page&hits=${count}); if (!response.ok) { throw new Error(HTTP ${response.status}: ${response.statusText}); }

    const data = await response.json();

    return data.hits.map((hit: any) => ({ id: hit.objectID, title: hit.title, url: hit.url || https://news.ycombinator.com/item?id=${hit.objectID}, source: 'hackernews', points: hit.points || 0, comments: hit.num_comments || 0, timestamp: new Date(hit.created_at).toISOString(), tags: hit._tags || [] })); } catch (error) { console.error('获取 Hacker News 失败:', error); return []; } }

/**

  • 从 Hacker News RSS 获取新闻(备用方案) */ async function getHackerNewsRSS(count: number): Promise<TechNewsItem[]> { try { const feed = await parser.parseURL('https://news.ycombinator.com/rss');

    return feed.items.slice(0, count).map((item: any) => ({ id: item.guid || item.link, title: item.title || 'No title', url: item.link, source: 'hackernews', timestamp: item.pubDate || new Date().toISOString(), tags: ['hackernews', 'rss'] })); } catch (error) { console.error('获取 Hacker News RSS 失败:', error); return []; } }

/**

  • 获取技术新闻(主函数) */ async function getTechNews(count: number = 10): Promise<TechNewsItem[]> { console.error(正在获取技术新闻(${count}条)...);

// 优先使用 Hacker News API let news = await getHackerNews(count);

// 如果失败,尝试 RSS 备用 if (news.length === 0) { console.error('Hacker News API 失败,尝试 RSS...'); news = await getHackerNewsRSS(count); }

console.error(✅ 获取到 ${news.length} 条新闻); return news; }

/**

  • CLI 入口 */ async function main() { const args = process.argv.slice(2); const count = parseInt(args[0]) || 10;

try { const news = await getTechNews(count);

// 输出 JSON 格式(便于程序调用)
console.log(JSON.stringify(news, null, 2));

} catch (error) { console.error('❌ 获取新闻失败:'); console.error(error); process.exit(1); } }

// 如果直接运行此脚本 if (import.meta.main) { main(); }

// 导出供其他模块使用 export { getTechNews }; export type { TechNewsItem }; FILE:Tools/Lib/types.ts /**

  • GitHubTrends - 类型定义
  • 定义所有 TypeScript 接口和类型 */

/**

  • GitHub Trending 项目 */ export interface TrendingProject { rank: number; name: string; description: string; language: string; stars: string; starsThisPeriod: string; url: string; }

/**

  • 技术新闻条目 */ export interface TechNewsItem { id: string; title: string; url: string; source: string; // 'hackernews', 'reddit', etc. points?: number; comments?: number; timestamp: string; tags: string[]; }

/**

  • 仪表板生成选项 */ export interface DashboardOptions { period: 'daily' | 'weekly'; language?: string; limit: number; output: string; includeNews: boolean; newsCount: number; theme: 'light' | 'dark' | 'auto'; }

/**

  • 数据分析结果 */ export interface Analytics { languageDistribution: Record<string, number>; totalStars: number; topProject: TrendingProject; growthStats: { highest: TrendingProject; average: number; }; }

/**

  • Trending 查询选项(用于 GetTrending.ts) */ export interface TrendingOptions { period: "daily" | "weekly"; language?: string; limit: number; }

/**

  • 图表数据 */ export interface ChartData { labels: string[]; data: number[]; colors: string[]; }

/**

  • 模板渲染数据 / export interface TemplateData { title: string; generatedAt: string; period: string; projects: TrendingProject[]; news?: TechNewsItem[]; analytics: Analytics; options: DashboardOptions; } FILE:Tools/Lib/template-helpers.ts /*
  • Template Helpers
  • Handlebars 自定义辅助函数 */

import Handlebars from 'handlebars';

/**

  • 注册所有自定义辅助函数 */ export function registerHelpers(): void { // 格式化数字(添加千位分隔符) Handlebars.registerHelper('formatNumber', (value: number) => { return value.toLocaleString(); });

// 截断文本 Handlebars.registerHelper('truncate', (str: string, length: number = 100) => { if (str.length <= length) return str; return str.substring(0, length) + '...'; });

// 格式化日期 Handlebars.registerHelper('formatDate', (dateStr: string) => { const date = new Date(dateStr); return date.toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }); });

// JSON 序列化(用于内嵌数据) Handlebars.registerHelper('json', (context: any) => { return JSON.stringify(context); });

// 条件判断 Handlebars.registerHelper('eq', (a: any, b: any) => { return a === b; });

Handlebars.registerHelper('ne', (a: any, b: any) => { return a !== b; });

Handlebars.registerHelper('gt', (a: number, b: number) => { return a > b; });

Handlebars.registerHelper('lt', (a: number, b: number) => { return a < b; }); }

/**

  • 渲染模板 */ export async function renderTemplate( templatePath: string, data: any ): Promise { const templateContent = await Bun.file(templatePath).text(); const template = Handlebars.compile(templateContent); return template(data); }

export default { registerHelpers, renderTemplate }; FILE:Tools/Lib/visualization-helpers.ts /**

  • Visualization Helpers
  • 数据分析和可视化辅助函数 */

import type { TrendingProject, Analytics } from './types';

/**

  • 分析项目数据 */ export function analyzeData(projects: TrendingProject[]): Analytics { // 语言分布统计 const languageDistribution: Record<string, number> = {}; projects.forEach(project => { const lang = project.language; languageDistribution[lang] = (languageDistribution[lang] || 0) + 1; });

// 总 stars 数 const totalStars = projects.reduce((sum, project) => { return sum + parseInt(project.stars.replace(/,/g, '') || 0); }, 0);

// 找出 top project const topProject = projects.reduce((top, project) => { const topStars = parseInt(top.stars.replace(/,/g, '') || 0); const projStars = parseInt(project.stars.replace(/,/g, '') || 0); return projStars > topStars ? project : top; }, projects[0]);

// 增长统计 const projectsWithGrowth = projects.filter(p => p.starsThisPeriod); const growthValues = projectsWithGrowth.map(p => parseInt(p.starsThisPeriod.replace(/[+,]/g, '') || 0) );

const highestGrowth = projectsWithGrowth.reduce((highest, project) => { const highestValue = parseInt(highest.starsThisPeriod.replace(/[+,]/g, '') || 0); const projValue = parseInt(project.starsThisPeriod.replace(/[+,]/g, '') || 0); return projValue > highestValue ? project : highest; }, projectsWithGrowth[0] || projects[0]);

const averageGrowth = growthValues.length > 0 ? Math.round(growthValues.reduce((a, b) => a + b, 0) / growthValues.length) : 0;

// 提取唯一语言列表(用于筛选) const languages = Object.keys(languageDistribution).sort();

// 生成图表数据 const growthData = projects.slice(0, 10).map(p => ({ name: p.name.split('/')[1] || p.name, growth: parseInt(p.starsThisPeriod.replace(/[+,]/g, '') || 0) }));

return { languageDistribution, totalStars, topProject, growthStats: { highest: highestGrowth, average: averageGrowth }, languages, growthData }; }

/**

  • 格式化 stars 数字 */ export function formatStars(starsStr: string): number { return parseInt(starsStr.replace(/,/g, '') || 0); }

/**

  • 解析增长数值 */ export function parseGrowth(growthStr: string): number { if (!growthStr) return 0; return parseInt(growthStr.replace(/[+,]/g, '') || 0); }

export default { analyzeData, formatStars, parseGrowth }; FILE:Templates/dashboard.hbs

GitHub Trending Dashboard - {{period}}

🚀 GitHub Trending Dashboard

周期: {{period}} | 生成时间: {{generatedAt}}

<!-- 统计概览 -->
<section class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
  <div class="stat-card rounded-xl p-6 text-white shadow-lg">
    <h3 class="text-lg font-semibold opacity-90">项目总数</h3>
    <p class="text-4xl font-bold mt-2">{{projects.length}}</p>
    <p class="text-sm opacity-75 mt-1">{{period}} 热门趋势</p>
  </div>

  <div class="bg-gradient-to-br from-green-500 to-emerald-600 rounded-xl p-6 text-white shadow-lg">
    <h3 class="text-lg font-semibold opacity-90">总 Stars 数</h3>
    <p class="text-4xl font-bold mt-2">{{analytics.totalStars}}</p>
    <p class="text-sm opacity-75 mt-1">所有项目总计</p>
  </div>

  <div class="bg-gradient-to-br from-orange-500 to-red-500 rounded-xl p-6 text-white shadow-lg">
    <h3 class="text-lg font-semibold opacity-90">最热项目</h3>
    <p class="text-xl font-bold mt-2 truncate">{{analytics.topProject.name}}</p>
    <p class="text-sm opacity-75 mt-1">{{analytics.topProject.stars}} stars</p>
  </div>
</section>

<!-- 筛选和搜索 -->
<section class="bg-white rounded-xl shadow-sm p-6 mb-8">
  <div class="flex flex-wrap gap-4 items-center">
    <div class="flex-1 min-w-64">
      <label class="block text-sm font-medium text-gray-700 mb-1">搜索项目</label>
      <input
        type="text"
        id="searchInput"
        placeholder="按名称或描述搜索..."
        class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-github-accent focus:border-transparent"
        oninput="filterProjects()"
      >
    </div>

    <div>
      <label class="block text-sm font-medium text-gray-700 mb-1">语言筛选</label>
      <select
        id="languageFilter"
        class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-github-accent focus:border-transparent"
        onchange="filterProjects()"
      >
        <option value="all">全部语言</option>
        {{#each analytics.languages}}
          <option value="{{this}}">{{this}}</option>
        {{/each}}
      </select>
    </div>

    <div>
      <label class="block text-sm font-medium text-gray-700 mb-1">排序方式</label>
      <select
        id="sortSelect"
        class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-github-accent focus:border-transparent"
        onchange="sortProjects()"
      >
        <option value="rank">排名</option>
        <option value="stars">总 Stars</option>
        <option value="growth">本期增长</option>
      </select>
    </div>
  </div>
</section>

<!-- 语言分布图表 -->
<section class="bg-white rounded-xl shadow-sm p-6 mb-8">
  <h2 class="text-2xl font-bold text-gray-900 mb-4">📊 语言分布</h2>
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
    <div>
      <canvas id="languageChart"></canvas>
    </div>
    <div>
      <canvas id="growthChart"></canvas>
    </div>
  </div>
</section>

<!-- Trending Projects -->
<section class="mb-8">
  <h2 class="text-2xl font-bold text-gray-900 mb-4">🔥 热门项目</h2>
  <div id="projects-container" class="grid grid-cols-1 gap-4">
    {{#each projects}}
    <div class="project-card bg-white rounded-xl shadow-sm p-6 border border-gray-200"
         data-rank="{{rank}}"
         data-language="{{language}}"
         data-stars="{{stars}}"
         data-growth="{{starsThisPeriod}}"
         data-name="{{name}}"
         data-description="{{description}}">
      <div class="flex items-start justify-between">
        <div class="flex-1">
          <div class="flex items-center gap-3 mb-2">
            <span class="text-2xl font-bold text-github-accent">#{{rank}}</span>
            <h3 class="text-xl font-semibold text-gray-900">
              <a href="{{url}}" target="_blank" class="hover:text-github-accent">{{name}}</a>
            </h3>
            <span class="badge bg-blue-100 text-blue-800">{{language}}</span>
          </div>
          <p class="text-gray-600 mb-3">{{description}}</p>
          <div class="flex items-center gap-4 text-sm text-gray-500">
            <span>⭐ {{stars}} stars</span>
            {{#if starsThisPeriod}}
              <span class="text-green-600 font-semibold">(+{{starsThisPeriod}} this {{../period}})</span>
            {{/if}}
          </div>
        </div>
        <a href="{{url}}" target="_blank" class="px-4 py-2 bg-github-accent text-white rounded-lg hover:bg-blue-600 transition font-medium">
          View →
        </a>
      </div>
    </div>
    {{/each}}
  </div>
</section>

<!-- Tech News -->
{{#if news}}
<section class="mb-8">
  <h2 class="text-2xl font-bold text-gray-900 mb-4">📰 技术资讯</h2>
  <div class="grid grid-cols-1 gap-4">
    {{#each news}}
    <div class="news-item bg-white rounded-xl shadow-sm p-5 hover:shadow-md transition">
      <div class="flex items-start justify-between">
        <div class="flex-1">
          <h3 class="text-lg font-semibold text-gray-900 mb-1">
            <a href="{{url}}" target="_blank" class="hover:text-github-accent">{{title}}</a>
          </h3>
          <div class="flex items-center gap-4 text-sm text-gray-500">
            <span class="text-orange-600">📰 {{source}}</span>
            {{#if points}}
              <span>⬆️ {{points}} points</span>
            {{/if}}
            {{#if comments}}
              <span>💬 {{comments}} comments</span>
            {{/if}}
          </div>
        </div>
      </div>
    </div>
    {{/each}}
  </div>
</section>
{{/if}}

由 GitHubTrends Skill 生成 | 数据来源:GitHub 和 Hacker News

FILE:Workflows/GenerateDashboard.md # GenerateDashboard Workflow

生成交互式数据可视化仪表板的工作流程。

Description

这个工作流使用 GenerateDashboard.ts 工具从 GitHub 获取 trending 项目,并生成交互式 HTML 仪表板,支持:

  • 项目卡片展示
  • 语言分布饼图
  • Stars 增长柱状图
  • 技术新闻列表
  • 实时筛选、排序、搜索功能

When to Use

当用户请求以下任何内容时使用此工作流:

  • "生成 GitHub trending 仪表板"
  • "创建趋势网页"
  • "生成可视化报告"
  • "export trending dashboard"
  • "生成交互式网页"

Workflow Steps

Step 1: 确定参数

向用户确认或推断以下参数:

  • 时间周期: daily (每日) 或 weekly (每周,默认)
  • 编程语言: 可选(如 TypeScript, Python, Go, Rust等)
  • 项目数量: 默认10个
  • 包含新闻: 是否包含技术新闻
  • 新闻数量: 默认10条
  • 输出路径: 默认 ./github-trends.html

Step 2: 执行工具

运行 GenerateDashboard.ts 工具:

# 基本用法(本周,10个项目)
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts

# 指定语言和新闻
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts \
  --period weekly \
  --language TypeScript \
  --limit 20 \
  --include-news \
  --news-count 15 \
  --output ~/trends.html

# 每日趋势
bun ~/.claude/skills/GitHubTrends/Tools/GenerateDashboard.ts \
  --period daily \
  --output ~/daily-trends.html

Step 3: 显示结果

工具会自动:

  1. 获取 GitHub trending 数据
  2. 获取技术新闻(如果启用)
  3. 分析数据生成统计信息
  4. 渲染 HTML 模板
  5. 保存到指定路径

Step 4: 验证和打开

生成的 HTML 文件包含:

  • ✅ 响应式布局
  • ✅ 项目卡片展示
  • ✅ 语言分布饼图
  • ✅ Stars 增长柱状图
  • ✅ 实时筛选功能
  • ✅ 排序功能
  • ✅ 搜索功能
  • ✅ 技术新闻列表

Example Usage

Example 1: 基本仪表板

User: "生成本周 GitHub trending 仪表板"

Assistant:
运行 GenerateDashboard 工具...
[执行命令,生成 /tmp/github-trends.html]
✅ 仪表板生成成功!已在浏览器中打开。

Example 2: 包含新闻的仪表板

User: "生成 TypeScript 项目的每日趋势,包含新闻"

Assistant:
生成 TypeScript 每日趋势仪表板,包含技术新闻...
[执行命令:--period daily --language TypeScript --include-news]
✅ 仪表板已生成到 ~/Downloads/ts-daily-trends.html

Example 3: 自定义输出

User: "生成一个包含 20 个项目的仪表板,保存到桌面"

Assistant:
生成 20 个项目的趋势仪表板...
[执行命令:--limit 20 --output ~/Desktop/github-trends.html]
✅ 完成!文件已保存到桌面

Tool Options

参数 说明 默认值 可选值
--period 时间周期 weekly daily, weekly
--language 编程语言筛选 全部 TypeScript, Python, Go, Rust等
--limit 返回项目数量 10 任意正整数
--include-news 包含技术新闻 false -
--news-count 新闻数量 10 任意正整数
--theme 主题 auto light, dark, auto
--output 输出文件路径 ./github-trends.html 任意路径

Output Features

数据可视化

  • 语言分布饼图: 展示各编程语言的项目占比
  • Stars 增长柱状图: 展示前 10 名项目的 stars 增长

交互功能

  • 搜索: 按项目名称或描述搜索
  • 筛选: 按编程语言筛选
  • 排序: 按排名、总 stars、周期内增长排序

响应式设计

  • 支持桌面、平板、手机
  • 使用 Tailwind CSS 构建美观界面
  • GitHub 风格配色

Error Handling

如果遇到错误:

  1. 网络错误: 检查网络连接,确保能访问 GitHub
  2. 解析失败: GitHub 页面结构可能变化,工具会显示调试信息
  3. 文件写入失败: 检查输出路径的写权限

Voice Notification

执行此工作流时发送语音通知:

curl -s -X POST http://localhost:8888/notify \
  -H "Content-Type: application/json" \
  -d '{"message": "正在生成 GitHub Trending Dashboard..."}' \
  > /dev/null 2>&1 &

并输出文本通知:

Running the **GenerateDashboard** workflow from the **GitHubTrends** skill...

Integration with Other Skills

  • Browser: 验证生成的 HTML 页面效果
  • System: 保存仪表板快照到 MEMORY/
  • OSINT: 分析技术栈趋势

Notes

  • 数据每小时更新一次(GitHub trending 更新频率)
  • 生成的 HTML 是完全独立的,无需服务器
  • 所有依赖通过 CDN 加载(Tailwind CSS, Chart.js)
  • 支持离线查看(图表已内嵌数据)

Advanced Usage

批量生成

# 生成多个语言的仪表板
for lang in TypeScript Python Go Rust; do
  bun Tools/GenerateDashboard.ts \
    --language $lang \
    --output ~/trends-$lang.html
done

定时任务

# 每小时生成一次快照
# 添加到 crontab:
0 * * * * cd ~/.claude/skills/GitHubTrends && bun Tools/GenerateDashboard.ts --output ~/trends-$(date +%H).html

定制主题

通过修改 Templates/dashboard.hbs 可以自定义:

  • 配色方案
  • 布局结构
  • 添加新的图表类型
  • 添加新的交互功能

Reviews (0)

Sign in to write a review.

No reviews yet. Be the first to review!

Comments (0)

Sign in to join the discussion.

No comments yet. Be the first to share your thoughts!

Compatible Platforms

Pricing

Free

Related Configs