Initial commit: Hermes Agent skills collection

- Trading skills (OKX, dividend, lottery, quantitative)
- Creative skills (ASCII art, diagrams, video)
- Development skills (GitHub, debugging, TDD)
- Research skills (arXiv, blog monitoring)
- Productivity skills (email, documents, notes)
- MCP integration skills
- Custom user skills
This commit is contained in:
Hermes Skills Manager
2026-07-05 02:31:15 -04:00
commit 6770bc9b9d
908 changed files with 239614 additions and 0 deletions
@@ -0,0 +1,30 @@
# Cron 时区对照表
cron 调度使用服务器本地时区 **America/New_York**。
## 目标 → cron 表达式
| 用户时间 | 服务器时间 | cron 表达式 |
|----------|-----------|-------------|
| 北京时间 08:00 | EDT 20:00 / EST 19:00 | `0 20 * * *` |
| 北京时间 20:00 | EDT 08:00 / EST 07:00 | `0 8 * * *` |
| 纽约时间 08:00 | EDT 08:00 / EST 08:00 | `0 8 * * *` |
| 纽约时间 20:00 | EDT 20:00 / EST 20:00 | `0 20 * * *` |
## 关键换算
```
北京时间 (CST, UTC+8):
EDT (UTC-4): CST = EDT + 12h
EST (UTC-5): CST = EST + 13h
服务器本地 (America/New_York):
EDT (夏令时, 3月-11月): UTC-4
EST (冬令时, 11月-3月): UTC-5
```
## 最佳实践
- 北京时间用户:偏好北京时间晚8点 → 设 `0 8 * * *`(服务器8am)
- 北京时间冬令时偏差约1小时(自动跟随UTC,无需手动调整)
- 纽约本地用户:直接用本地时间,无需换算
@@ -0,0 +1,86 @@
# GitHub API Browser Fallback — 当 terminal/curl 不可用时
## 核心技巧
用 `browser_navigate` 直接访问 GitHub API(无需认证的公开端点),然后 `browser_console` 提取 JSON。
## 每次操作的三步模式
```
1. browser_navigate → API URL
2. browser_console → JSON.parse(document.body.innerText).items.map(...)
3. 处理数据,再 navigate 下一个查询
```
## 推荐查询模板
### 查询 1:近7天新建高星项目(主力)⭐ 最重要
```
https://api.github.com/search/repositories?q=created:>YYYY-MM-DD+stars:>200&sort=stars&per_page=20
```
将 `YYYY-MM-DD` 替换为7天前日期。⚠️ 阈值不要低于 `stars:>200`,否则垃圾仓库淹没结果。
### 查询 2:老牌大项目近期活跃(补充上下文)
```
https://api.github.com/search/repositories?q=pushed:>YYYY-MM-DD+stars:>5000&sort=stars&per_page=15
```
发现大项目的重大更新(如新版本发布)。提供"老牌活跃"维度,与查询1的"新项目爆发"互补。
### 查询 3:近30天快速增长项目(可选)
```
https://api.github.com/search/repositories?q=created:>YYYY-MM-DD+stars:>500&sort=stars&per_page=20
```
### 查询 4:特定语言趋势(按需)
```
https://api.github.com/search/repositories?q=language:rust+created:>YYYY-MM-DD+stars:>100&sort=stars&per_page=15
```
### ⚠️ 避免:极新鲜 + 低阈值查询
```
❌ created:>2天前+stars:>50 → 几乎全是垃圾仓库
```
2026-06-19 实测:`created:>2026-06-17+stars:>50` 返回的20个结果中,18个是模板化垃圾仓库(Star数全是110-121,0 forks,描述模板化)。参见 `references/spam-detection.md` 中的实战案例。
## JS 提取模板(每个查询复用,必须用 IIFE 包裹)
```javascript
// ⚠️ 必须用 IIFE 包裹,避免变量重复声明错误(browser_console 共享 JS 上下文)
(function(){
var d = JSON.parse(document.body.innerText);
return d.items.map(function(r) {
return {
name: r.full_name,
desc: (r.description||'').slice(0,200),
stars: r.stargazers_count,
lang: r.language,
created: r.created_at.slice(0,10),
forks: r.forks_count,
topics: (r.topics||[]).slice(0,6)
};
});
})()
```
## 三查询实战 Playbook(2026-06-19 验证)
当 trending 页面完全不可用时,用以下三个查询组合获取完整日报数据:
| 步骤 | 查询 | 数据量 | 用途 |
|------|------|--------|------|
| ① | `created:>7天前+stars:>200` | ~15-20 个 | 新项目爆发(主数据源) |
| ② | `pushed:>昨天+stars:>5000` | ~15 个 | 老牌活跃项目(上下文补充) |
| ③ | `created:>14天前+stars:>300` | ~15 个 | 近两周中等阈值(补漏) |
**执行顺序**:每个查询独立 `browser_navigate` → `browser_console` 提取 → 再下一个。
**合并策略**:三轮结果按 `full_name` 去重后,选 TOP 10 分析。查询①的新项目优先,查询②的大项目作为趋势补充。
**注意**:不要用 `created:>2天前+stars:>50`,该查询几乎全是垃圾仓库(见上方警告)。
## 注意事项
- GitHub API 未认证限速:10 requests/minute,足够完成日报
- 每个查询需要单独 `browser_navigate`,不要在同一个 page 做多次 fetch
- API 返回的 `stargazers_count` 是总星数,不是日增——需要通过 `created` 日期和星数推算热度
- 对于真正的"今日增速"数据,API 无法直接提供,需要对比不同时间点的查询结果
@@ -0,0 +1,71 @@
# GitHub API 搜索查询合集
用于按语言、Stars、创建时间等维度批量发现高星项目。
## 基础查询
```bash
# 高星项目(>1000 stars,最近有更新)
https://api.github.com/search/repositories?q=stars:>1000&sort=stars&order=desc&per_page=25
# 本月新项目(近30天创建,>100 stars)
https://api.github.com/search/repositories?q=created:>2026-04-26+stars:>100&sort=stars&order=desc
# 本周爆发项目(本周创建,>50 stars)
https://api.github.com/search/repositories?q=created:>2026-05-19+stars:>50&sort=stars&order=desc
```
## 按语言筛选
```bash
# Rust 高星项目
https://api.github.com/search/repositories?q=language:rust+stars:>500&sort=stars&order=desc
# Python AI/ML 项目
https://api.github.com/search/repositories?q=language:python+topic:ai+stars:>500&sort=stars&order=desc
# TypeScript 开发者工具
https://api.github.com/search/repositories?q=language:typescript+topic:developer-tools+stars:>200&sort=stars&order=desc
# Go 云原生项目
https://api.github.com/search/repositories?q=language:go+topic:cloud-native+stars:>500&sort=stars&order=desc
```
## 按主题筛选
```bash
# LLM Agent 框架
https://api.github.com/search/repositories?q=topic:llm-agent+stars:>200&sort=stars&order=desc
# RAG 项目
https://api.github.com/search/repositories?q=topic:rag+stars:>100&sort=stars&order=desc
# 本地 LLM 工具
https://api.github.com/search/repositories?q=topic:local-llm+stars:>100&sort=stars&order=desc
```
## 组合查询
```bash
# 2025年后创建的高星 Rust 项目
https://api.github.com/search/repositories?q=language:rust+created:>2025-01-01+stars:>1000&sort=stars&order=desc
# 近3个月的热门 AI 工具(>500 stars)
https://api.github.com/search/repositories?q=language:python+topic:ai+topic:tools+created:>2026-02-25+stars:>200&sort=stars&order=desc
```
## 获取完整数据
GitHub API 返回 JSON,直接用 curl 处理:
```bash
curl -s "https://api.github.com/search/repositories?q=stars:>1000&sort=stars&per_page=10" | jq '[.items[] | {name: .full_name, stars: .stargazers_count, desc: .description, lang: .language, url: .html_url, topics: .topics}]'
```
## 注意事项
- GitHub API 未认证限制 60 req/h,认证后 5000 req/h
- `per_page` 最大 100
- 日期格式: `YYYY-MM-DD`
- 用 `pushed:>YYYY-MM-DD` 筛选活跃项目
- `topic:` 使用仓库的 GitHub Topics 标签
@@ -0,0 +1,70 @@
# GitHub Trending 垃圾仓库识别
## 自动化检测方法
在 `browser_console` 中运行以下代码(记得用 IIFE 包裹)来批量检测可疑仓库:
```javascript
(function(){
const d = JSON.parse(document.body.innerText);
const items = d.items;
// 1. 检测相同 Star 数的仓库群(刷星信号)
const sg = {};
items.forEach(r => {
const s = r.stargazers_count;
if (!sg[s]) sg[s] = [];
sg[s].push(r.full_name);
});
const suspiciousStars = Object.entries(sg).filter(([s, names]) => names.length > 1);
// 2. 检测无描述的仓库
const noDesc = items.filter(r => !r.description).map(r => r.full_name);
// 3. 检测 Fork 为 0 但 Star > 50 的仓库(非自然增长)
const noForkHighStar = items.filter(r => r.forks_count === 0 && r.stargazers_count > 50)
.map(r => ({name: r.full_name, stars: r.stargazers_count}));
return JSON.stringify({suspiciousStars, noDesc, noForkHighStar}, null, 2);
})()
```
## 手动识别信号
| 信号 | 说明 | 处理 |
|------|------|------|
| 多个仓库 Star 数完全相同 | 如全是 322⭐,批量刷星 | 过滤掉全部 |
| 无描述 | `description` 为空或 null | 标记可疑,需人工判断 |
| 描述模板化 | "Simple and clean standalone desktop..." | 过滤 |
| 同一语言 + 重复话题标签 | 常为 C++/C# 批量生成 | 过滤 |
| Fork=0 但 Star>50 | 非自然增长模式 | 标记可疑 |
| 含关键词堆砌 | "download crack free 2026" | 过滤 |
| 盗版工具 | 如 "Office Activated" | 过滤 |
## 2026-06-09 实战案例
今日检测到的垃圾仓库:
- `Unicornronote/Microsoft-Office-Activated` (370⭐) — Office 盗版激活工具
- `YuvBindal/produck-oss` + `Parcle-AI/parcle-memory` — 均为 322⭐,0 forks,无描述,批量刷星
- `wy51ai/edulab`、`vorpus/performativeUI` — 无描述
过滤后保留 14 个有效仓库,选取 TOP 10 进行分析。
## 2026-06-19 实战案例:极新鲜查询的垃圾洪水
查询 `created:>2026-06-17+stars:>50` 返回 20 个结果,其中 18 个是垃圾仓库:
**典型特征**:
- Star 数高度集中:110-121⭐(批量刷星痕迹明显)
- 全部 0 forks
- 描述模板化:"XXX workflow — YYY on Windows"
- 仓库名模式:`RandomWord/SoftwareName-2026`
- topics 堆砌:每个仓库恰好 5 个 topic,格式统一
**示例垃圾仓库**:
- `MstKail/polymarket-trading-bot-services-polyedge365` (261⭐, 710 forks) — 唯一例外,但描述为关键词堆砌
- `gasguardianarouse/SketchUp-Pro-2026` (116⭐, 0 forks) — 模板描述
- `KeeperDefine/ExitLag-2026` (115⭐, 0 forks) — 模板描述
- `ManacleBat38/QuickBooks-Desktop-2026` (114⭐, 0 forks) — 模板描述
**教训**:`stars:>50` 阈值对 2 天内新建仓库太低,必须用 `stars:>200` + 7 天窗口。
@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""Parse GitHub Trending page via curl + regex.
Use this when browser_navigate to GitHub trending fails (CDP timeout).
Write to /tmp/parse_trending.py, then run: python3 /tmp/parse_trending.py
Usage:
python3 /tmp/parse_trending.py # daily trending (default)
python3 /tmp/parse_trending.py weekly # this week
python3 /tmp/parse_trending.py monthly # this month
Output: JSON array of repo objects.
"""
import subprocess, re, json, sys
since = sys.argv[1] if len(sys.argv) > 1 else "daily"
url = f"https://github.com/trending?since={since}"
result = subprocess.run(['curl', '-s', url], capture_output=True, text=True)
html = result.stdout
# Find all article elements (each is a trending repo card)
articles = re.findall(r'<article[^>]*>(.*?)</article>', html, re.DOTALL)
results = []
for art in articles:
# Extract repo name from h2 > a href=\"/owner/repo\"
# ⚠️ The FIRST <a> in <h2> is often a /sponsors/ or /login? link, NOT the repo.
# Skip any href starting with "sponsors/" or "login?".
h2_section = re.search(r'<h2[^>]*>(.*?)</h2>', art, re.DOTALL)
if h2_section:
repo_hrefs = re.findall(r'href=\"/[^\"#]+/[^\"]+\"', h2_section.group(1))
# Pick the first href that is NOT a sponsors or login link
name = ''
for href in repo_hrefs:
href_val = href.split('"')[1] # extract value from href="..."
if not href_val.startswith('/sponsors/') and not href_val.startswith('/login?'):
name = href_val.lstrip('/')
break
else:
# Fallback: scan the whole article
all_hrefs = re.findall(r'href=\"/[^\"#]+/[^\"]+\"', art)
for href in all_hrefs:
href_val = href.split('"')[1]
if not href_val.startswith('/sponsors/') and not href_val.startswith('/login?'):
name = href_val.lstrip('/')
break
else:
name = ''
# Extract description from <p class="col-9...>
desc_match = re.search(r'<p class=\"col-9[^>]*>(.*?)</p>', art, re.DOTALL)
desc = desc_match.group(1).strip() if desc_match else ''
# Extract total stars from stargazers link
stars_match = re.search(r'href=\"[^\"]*stargazers\"[^>]*>\s*(.*?)\s*</a>', art, re.DOTALL)
stars = ''
if stars_match:
s = stars_match.group(1).strip()
s = re.sub(r'[,\s]', '', s)
stars = s
# Extract language (known languages only)
lang_match = re.search(
r'<span[^>]*>(TypeScript|Python|JavaScript|Rust|Go|C\+\+|Java|Kotlin|Swift|Ruby|PHP|Shell|HTML|CSS|Jupyter Notebook)</span>',
art
)
lang = lang_match.group(1) if lang_match else ''
# Extract stars today / this week / this month
stars_period = ''
for span in re.finditer(r'<span[^>]*>(.*?)</span>', art, re.DOTALL):
t = span.group(1).strip()
if 'stars today' in t or 'stars this week' in t or 'stars this month' in t:
stars_period = t
if name:
results.append({
'name': name,
'desc': desc,
'stars': stars,
'lang': lang,
'starsPeriod': stars_period,
})
print(json.dumps(results, ensure_ascii=False, indent=2))