@opendirectory.dev/skills 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/claude-md-generator/.env.example +7 -0
- package/.claude/skills/claude-md-generator/README.md +78 -0
- package/.claude/skills/claude-md-generator/SKILL.md +248 -0
- package/.claude/skills/claude-md-generator/evals/evals.json +35 -0
- package/.claude/skills/claude-md-generator/references/section-guide.md +175 -0
- package/dist/e2e.test.d.ts +1 -0
- package/dist/e2e.test.js +62 -0
- package/dist/fs-adapters.d.ts +4 -0
- package/dist/fs-adapters.js +101 -0
- package/dist/fs-adapters.test.d.ts +1 -0
- package/dist/fs-adapters.test.js +108 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +211 -0
- package/dist/transformers.d.ts +6 -0
- package/dist/transformers.js +2 -0
- package/package.json +25 -0
- package/registry.json +226 -0
- package/skills/blog-cover-image-cli/.github/workflows/publish.yml +19 -0
- package/skills/blog-cover-image-cli/LICENSE +15 -0
- package/skills/blog-cover-image-cli/README.md +126 -0
- package/skills/blog-cover-image-cli/SKILL.md +7 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/README.md +30 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/SKILL.md +72 -0
- package/skills/blog-cover-image-cli/bin/cli.js +226 -0
- package/skills/blog-cover-image-cli/examples/100x_UX_Research_AI_Agent.png +0 -0
- package/skills/blog-cover-image-cli/examples/Firecrawl-supabase-bolt.png +0 -0
- package/skills/blog-cover-image-cli/examples/Git-City_Case_study_Cover_Image.jpg +0 -0
- package/skills/blog-cover-image-cli/examples/THE DISTRIBUTION LAYER (2).png +0 -0
- package/skills/blog-cover-image-cli/examples/canva-perplexity-duolingo-cover-image.png +0 -0
- package/skills/blog-cover-image-cli/examples/gamma-mistral-veed.png +0 -0
- package/skills/blog-cover-image-cli/examples/server-survival-case-study-cover-image(1).png +0 -0
- package/skills/blog-cover-image-cli/examples/viral-meme-automation.png +0 -0
- package/skills/blog-cover-image-cli/index.js +2 -0
- package/skills/blog-cover-image-cli/package-lock.json +2238 -0
- package/skills/blog-cover-image-cli/package.json +37 -0
- package/skills/blog-cover-image-cli/src/geminiGenerator.js +126 -0
- package/skills/blog-cover-image-cli/src/imageValidator.js +54 -0
- package/skills/blog-cover-image-cli/src/logoFetcher.js +86 -0
- package/skills/claude-md-generator/.env.example +7 -0
- package/skills/claude-md-generator/README.md +78 -0
- package/skills/claude-md-generator/SKILL.md +254 -0
- package/skills/claude-md-generator/evals/evals.json +35 -0
- package/skills/claude-md-generator/references/section-guide.md +175 -0
- package/skills/cook-the-blog/README.md +86 -0
- package/skills/cook-the-blog/SKILL.md +130 -0
- package/skills/dependency-update-bot/.env.example +13 -0
- package/skills/dependency-update-bot/README.md +101 -0
- package/skills/dependency-update-bot/SKILL.md +376 -0
- package/skills/dependency-update-bot/evals/evals.json +45 -0
- package/skills/dependency-update-bot/references/changelog-patterns.md +201 -0
- package/skills/docs-from-code/.env.example +13 -0
- package/skills/docs-from-code/README.md +97 -0
- package/skills/docs-from-code/SKILL.md +160 -0
- package/skills/docs-from-code/evals/evals.json +29 -0
- package/skills/docs-from-code/references/extraction-guide.md +174 -0
- package/skills/docs-from-code/references/output-template.md +135 -0
- package/skills/docs-from-code/scripts/extract_py.py +238 -0
- package/skills/docs-from-code/scripts/extract_ts.ts +284 -0
- package/skills/docs-from-code/scripts/package.json +18 -0
- package/skills/explain-this-pr/README.md +74 -0
- package/skills/explain-this-pr/SKILL.md +130 -0
- package/skills/explain-this-pr/evals/evals.json +35 -0
- package/skills/google-trends-api-skills/README.md +78 -0
- package/skills/google-trends-api-skills/SKILL.md +7 -0
- package/skills/google-trends-api-skills/google-trends-api/SKILL.md +163 -0
- package/skills/google-trends-api-skills/google-trends-api/references/api-responses.md +188 -0
- package/skills/google-trends-api-skills/google-trends-api/scripts/discover_keywords.py +344 -0
- package/skills/google-trends-api-skills/seo-keyword-research/SKILL.md +205 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/keyword-placement-guide.md +89 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/tech-blog-examples.md +207 -0
- package/skills/google-trends-api-skills/seo-keyword-research/scripts/blog_seo_research.py +373 -0
- package/skills/hackernews-intel/.env.example +33 -0
- package/skills/hackernews-intel/README.md +161 -0
- package/skills/hackernews-intel/SKILL.md +156 -0
- package/skills/hackernews-intel/evals/evals.json +35 -0
- package/skills/hackernews-intel/package.json +15 -0
- package/skills/hackernews-intel/scripts/monitor-hn.js +258 -0
- package/skills/kill-the-standup/.env.example +22 -0
- package/skills/kill-the-standup/README.md +84 -0
- package/skills/kill-the-standup/SKILL.md +169 -0
- package/skills/kill-the-standup/evals/evals.json +35 -0
- package/skills/kill-the-standup/references/standup-format.md +102 -0
- package/skills/linkedin-post-generator/.env.example +14 -0
- package/skills/linkedin-post-generator/README.md +107 -0
- package/skills/linkedin-post-generator/SKILL.md +228 -0
- package/skills/linkedin-post-generator/evals/evals.json +35 -0
- package/skills/linkedin-post-generator/references/linkedin-format.md +216 -0
- package/skills/linkedin-post-generator/references/output-template.md +154 -0
- package/skills/llms-txt-generator/.env.example +18 -0
- package/skills/llms-txt-generator/README.md +142 -0
- package/skills/llms-txt-generator/SKILL.md +176 -0
- package/skills/llms-txt-generator/evals/evals.json +35 -0
- package/skills/llms-txt-generator/references/llms-txt-spec.md +88 -0
- package/skills/llms-txt-generator/references/output-template.md +76 -0
- package/skills/llms-txt-generator/test-output/genzcareer.in/llms.txt +31 -0
- package/skills/luma-attendees-scraper/README.md +170 -0
- package/skills/luma-attendees-scraper/SKILL.md +7 -0
- package/skills/luma-attendees-scraper/luma_attendees_export.js +223 -0
- package/skills/meeting-brief-generator/.env.example +21 -0
- package/skills/meeting-brief-generator/README.md +90 -0
- package/skills/meeting-brief-generator/SKILL.md +275 -0
- package/skills/meeting-brief-generator/evals/evals.json +35 -0
- package/skills/meeting-brief-generator/references/brief-format.md +114 -0
- package/skills/meeting-brief-generator/references/output-template.md +150 -0
- package/skills/meta-ads-skill/README.md +100 -0
- package/skills/meta-ads-skill/SKILL.md +7 -0
- package/skills/meta-ads-skill/meta-ads-skill/SKILL.md +41 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/report_templates.md +47 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/workflows.md +51 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/auth_check.py +22 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/formatters.py +46 -0
- package/skills/newsletter-digest/.env.example +20 -0
- package/skills/newsletter-digest/README.md +147 -0
- package/skills/newsletter-digest/SKILL.md +221 -0
- package/skills/newsletter-digest/evals/evals.json +35 -0
- package/skills/newsletter-digest/feeds.json +7 -0
- package/skills/newsletter-digest/package.json +15 -0
- package/skills/newsletter-digest/references/digest-format.md +123 -0
- package/skills/newsletter-digest/references/output-template.md +136 -0
- package/skills/newsletter-digest/scripts/fetch-feeds.js +141 -0
- package/skills/newsletter-digest/scripts/ghost-publish.js +147 -0
- package/skills/noise2blog/.env.example +16 -0
- package/skills/noise2blog/README.md +107 -0
- package/skills/noise2blog/SKILL.md +229 -0
- package/skills/noise2blog/evals/evals.json +35 -0
- package/skills/noise2blog/references/blog-format.md +188 -0
- package/skills/noise2blog/references/output-template.md +184 -0
- package/skills/outreach-sequence-builder/.env.example +12 -0
- package/skills/outreach-sequence-builder/README.md +108 -0
- package/skills/outreach-sequence-builder/SKILL.md +248 -0
- package/skills/outreach-sequence-builder/evals/evals.json +36 -0
- package/skills/outreach-sequence-builder/references/output-template.md +171 -0
- package/skills/outreach-sequence-builder/references/sequence-format.md +167 -0
- package/skills/outreach-sequence-builder/references/signal-playbook.md +117 -0
- package/skills/position-me/README.md +71 -0
- package/skills/position-me/SKILL.md +7 -0
- package/skills/position-me/position-me/SKILL.md +50 -0
- package/skills/position-me/position-me/references/EVALUATION_SOP.md +40 -0
- package/skills/position-me/position-me/references/REPORT_TEMPLATE.md +58 -0
- package/skills/position-me/position-me/scripts/extract_links.py +49 -0
- package/skills/pr-description-writer/README.md +81 -0
- package/skills/pr-description-writer/SKILL.md +141 -0
- package/skills/pr-description-writer/evals/evals.json +35 -0
- package/skills/pr-description-writer/references/pr-format-guide.md +145 -0
- package/skills/producthunt-launch-kit/.env.example +7 -0
- package/skills/producthunt-launch-kit/README.md +95 -0
- package/skills/producthunt-launch-kit/SKILL.md +380 -0
- package/skills/producthunt-launch-kit/evals/evals.json +35 -0
- package/skills/producthunt-launch-kit/references/copy-rules.md +124 -0
- package/skills/reddit-icp-monitor/.env.example +16 -0
- package/skills/reddit-icp-monitor/README.md +117 -0
- package/skills/reddit-icp-monitor/SKILL.md +271 -0
- package/skills/reddit-icp-monitor/evals/evals.json +40 -0
- package/skills/reddit-icp-monitor/references/icp-format.md +131 -0
- package/skills/reddit-icp-monitor/references/reply-rules.md +110 -0
- package/skills/reddit-post-engine/.env.example +13 -0
- package/skills/reddit-post-engine/README.md +103 -0
- package/skills/reddit-post-engine/SKILL.md +303 -0
- package/skills/reddit-post-engine/evals/evals.json +35 -0
- package/skills/reddit-post-engine/references/subreddit-playbook.md +156 -0
- package/skills/schema-markup-generator/.env.example +19 -0
- package/skills/schema-markup-generator/README.md +114 -0
- package/skills/schema-markup-generator/SKILL.md +192 -0
- package/skills/schema-markup-generator/evals/evals.json +35 -0
- package/skills/schema-markup-generator/references/json-ld-spec.md +263 -0
- package/skills/schema-markup-generator/references/output-template.md +556 -0
- package/skills/show-hn-writer/.env.example +14 -0
- package/skills/show-hn-writer/README.md +88 -0
- package/skills/show-hn-writer/SKILL.md +303 -0
- package/skills/show-hn-writer/evals/evals.json +35 -0
- package/skills/show-hn-writer/references/hn-rules.md +74 -0
- package/skills/show-hn-writer/references/title-formulas.md +93 -0
- package/skills/stargazer/README.md +79 -0
- package/skills/stargazer/SKILL.md +7 -0
- package/skills/stargazer/stargazer-skill/SKILL.md +58 -0
- package/skills/stargazer/stargazer-skill/assets/.env.example +18 -0
- package/skills/stargazer/stargazer-skill/scripts/convert_to_csv.py +63 -0
- package/skills/stargazer/stargazer-skill/scripts/count_emails.py +52 -0
- package/skills/stargazer/stargazer-skill/scripts/stargazer_deep_extractor.py +450 -0
- package/skills/tweet-thread-from-blog/.env.example +14 -0
- package/skills/tweet-thread-from-blog/README.md +109 -0
- package/skills/tweet-thread-from-blog/SKILL.md +177 -0
- package/skills/tweet-thread-from-blog/evals/evals.json +35 -0
- package/skills/tweet-thread-from-blog/references/output-template.md +193 -0
- package/skills/tweet-thread-from-blog/references/thread-format.md +107 -0
- package/skills/twitter-GTM-find-skill/README.md +43 -0
- package/skills/twitter-GTM-find-skill/SKILL.md +7 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/SKILL.md +37 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/references/icp-checklist.md +35 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/package.json +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/run_pipeline.sh +8 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/debug.ts +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/extractor.ts +79 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/icp-filter.ts +87 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/index.ts +94 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/scraper.ts +41 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/tsconfig.json +13 -0
- package/skills/yc-intent-radar-skill/README.md +39 -0
- package/skills/yc-intent-radar-skill/SKILL.md +7 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/SKILL.md +59 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/auth.js +29 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/db.js +62 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/export_radar_candidates.js +40 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package-lock.json +1525 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package.json +12 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/scraper.js +217 -0
- package/src/e2e.test.ts +35 -0
- package/src/fs-adapters.test.ts +91 -0
- package/src/fs-adapters.ts +65 -0
- package/src/index.ts +182 -0
- package/src/transformers.ts +6 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: show-hn-writer
|
|
3
|
+
description: ''
|
|
4
|
+
compatibility: [claude-code, gemini-cli, github-copilot]
|
|
5
|
+
author: OpenDirectory
|
|
6
|
+
version: 1.0.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Show HN Writer
|
|
10
|
+
|
|
11
|
+
Draft a Show HN post title and body that follows the unwritten rules of Hacker News: specific, honest, first-person, no marketing.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
**Critical rule:** Never use marketing language. No "game-changing", "revolutionary", "powerful", "robust", "seamless", "innovative", "best-in-class", or "streamline". Never write in third person about the product. Never ask readers to upvote, share, or check out other links.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Step 1: Gather Project Context
|
|
20
|
+
|
|
21
|
+
Check if the user has already provided enough context to write the post. You need:
|
|
22
|
+
|
|
23
|
+
- What the project does (one technical sentence)
|
|
24
|
+
- What problem it solves and who has that problem
|
|
25
|
+
- Why the builder made it (the honest story: scratch your own itch, side project, weekend hack)
|
|
26
|
+
- What makes it technically interesting or different from existing solutions
|
|
27
|
+
- Current state: alpha, beta, open source, free, paid, solo project, team
|
|
28
|
+
|
|
29
|
+
If any of these are missing, ask in a single message:
|
|
30
|
+
|
|
31
|
+
"To write your Show HN post, I need a few details:
|
|
32
|
+
1. What does [project name] do, technically? (one sentence)
|
|
33
|
+
2. Who has the problem it solves? (be specific: 'developers who...' not 'anyone who...')
|
|
34
|
+
3. Why did you build it? (the real story)
|
|
35
|
+
4. What's technically interesting about how it works?
|
|
36
|
+
5. What's the current state: open source? free? alpha?"
|
|
37
|
+
|
|
38
|
+
Do not proceed until you have answers to all five.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Step 2: Read Context Files (if available)
|
|
43
|
+
|
|
44
|
+
Check for project context files before asking:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
ls README.md 2>/dev/null && echo "README found"
|
|
48
|
+
ls CLAUDE.md 2>/dev/null && echo "CLAUDE.md found"
|
|
49
|
+
ls package.json 2>/dev/null && echo "package.json found"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
If README.md exists, read the first 100 lines. Extract: what it does, tech stack, how to run it, any stated motivation.
|
|
53
|
+
|
|
54
|
+
If you find enough context in the files, skip the Step 1 questions entirely or ask only what's missing.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Step 3: Draft the Title
|
|
59
|
+
|
|
60
|
+
The Show HN title must start with "Show HN:": this is required, not optional.
|
|
61
|
+
|
|
62
|
+
**Title format A: Product-First:**
|
|
63
|
+
```
|
|
64
|
+
Show HN: [Project Name] – [what it does in plain English]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Title format B: Outcome-Focused:**
|
|
68
|
+
```
|
|
69
|
+
Show HN: [Project Name] – [specific outcome] for [specific person]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Title rules:**
|
|
73
|
+
- 60-80 characters total (including "Show HN: ")
|
|
74
|
+
- No exclamation marks
|
|
75
|
+
- No adjectives ("fast", "simple", "easy", "powerful") unless they are literal technical specs
|
|
76
|
+
- The dash is an en dash (–), not a hyphen (-)
|
|
77
|
+
- No trailing punctuation
|
|
78
|
+
- Describe what it does, not what it could do for someone
|
|
79
|
+
|
|
80
|
+
Good examples:
|
|
81
|
+
- `Show HN: Zulip – Group chat that threads every conversation`
|
|
82
|
+
- `Show HN: Lite XL – A lightweight text editor written in C and Lua`
|
|
83
|
+
- `Show HN: Datasette – Instantly publish SQLite databases to the web`
|
|
84
|
+
|
|
85
|
+
Bad examples (never write these):
|
|
86
|
+
- `Show HN: The most powerful tool for managing your workflow` (adjective, no specifics)
|
|
87
|
+
- `Show HN: Check out my new project!` (no description, no name)
|
|
88
|
+
- `Show HN: I built a thing for developers` (vague)
|
|
89
|
+
|
|
90
|
+
Draft three title variants:
|
|
91
|
+
1. Product-First format
|
|
92
|
+
2. Outcome-Focused format
|
|
93
|
+
3. Technical-Angle format (lead with the interesting technical decision)
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Step 4: Draft the Body
|
|
98
|
+
|
|
99
|
+
The Show HN body is a builder talking to peers. It is not a product description. It is not a pitch.
|
|
100
|
+
|
|
101
|
+
**Structure:**
|
|
102
|
+
|
|
103
|
+
**Opening line:** One sentence, first-person, what you built. Not "Introducing X" or "X is a tool that". Just: "I built [X] because [reason]." or "For the past [N] months I've been working on [X]."
|
|
104
|
+
|
|
105
|
+
**The why:** Two to four sentences on why you made it. Was it a problem you had personally? Something frustrating at work? A technical curiosity? Be specific and honest. If you built it for fun, say so.
|
|
106
|
+
|
|
107
|
+
**How it works:** Three to six sentences on the technical approach. This is what HN readers care about. What's the interesting engineering decision? What did you learn? What tradeoff did you make and why? Name the specific technology choices.
|
|
108
|
+
|
|
109
|
+
**Current state:** One to two sentences. Is it open source? Free? Alpha? Looking for beta users? Solo project or team? How long have you been working on it?
|
|
110
|
+
|
|
111
|
+
**Invitation:** One sentence to close. Invite feedback, questions, or criticism. Never ask for upvotes or shares. Examples: "Would love to hear what you think." / "Happy to answer questions about the implementation." / "Criticism welcome: still early days."
|
|
112
|
+
|
|
113
|
+
**Body rules:**
|
|
114
|
+
- Write in first person throughout
|
|
115
|
+
- 150-350 words total
|
|
116
|
+
- No bullet points, no headers, no bold text
|
|
117
|
+
- No links in the body (the URL goes in the submission, not the body)
|
|
118
|
+
- No asking people to sign up, follow, or subscribe
|
|
119
|
+
- No comparison tables or feature lists
|
|
120
|
+
- If there's a demo or GitHub link, do NOT add it to the body: it goes in the URL field of the submission
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Step 5: Summarize Submission with Gemini
|
|
125
|
+
|
|
126
|
+
Write a Gemini request to evaluate the draft and check for Show HN anti-patterns:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
cat > /tmp/show-hn-review-request.json << 'ENDJSON'
|
|
130
|
+
{
|
|
131
|
+
"system_instruction": {
|
|
132
|
+
"parts": [{
|
|
133
|
+
"text": "You are a longtime Hacker News member reviewing a Show HN post draft. Your job is to catch anything that will hurt its reception: marketing language, vague descriptions, third-person writing, requests for upvotes/shares, adjectives without specifics, titles over 80 characters. For each issue found, state: the exact phrase, why it hurts, and a specific suggested replacement. If the post passes, say 'Passes review.' Output only the review: no commentary, no preamble. Do not use em dashes. Do not praise the post."
|
|
134
|
+
}]
|
|
135
|
+
},
|
|
136
|
+
"contents": [{
|
|
137
|
+
"parts": [{
|
|
138
|
+
"text": "DRAFT_POST_HERE"
|
|
139
|
+
}]
|
|
140
|
+
}],
|
|
141
|
+
"generationConfig": {
|
|
142
|
+
"temperature": 0.2,
|
|
143
|
+
"maxOutputTokens": 1024
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
ENDJSON
|
|
147
|
+
|
|
148
|
+
curl -s -X POST \
|
|
149
|
+
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
|
|
150
|
+
-H "Content-Type: application/json" \
|
|
151
|
+
-d @/tmp/show-hn-review-request.json \
|
|
152
|
+
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Replace `DRAFT_POST_HERE` with the full title and body text.
|
|
156
|
+
|
|
157
|
+
**If GEMINI_API_KEY is not set:** Skip this step. Proceed with the manual self-QA in Step 6.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Step 6: Self-QA
|
|
162
|
+
|
|
163
|
+
Before presenting the final output, check each item:
|
|
164
|
+
|
|
165
|
+
**Title checks:**
|
|
166
|
+
- [ ] Starts with exactly "Show HN:" (capital H, capital N, colon, space)
|
|
167
|
+
- [ ] 60-80 characters total
|
|
168
|
+
- [ ] Contains no marketing adjectives
|
|
169
|
+
- [ ] Describes what the product does, not what it will do for someone
|
|
170
|
+
- [ ] No exclamation marks
|
|
171
|
+
|
|
172
|
+
**Body checks:**
|
|
173
|
+
- [ ] Opens in first person ("I built...", "For the past N months...", "I've been working on...")
|
|
174
|
+
- [ ] 150-350 words
|
|
175
|
+
- [ ] Contains at least one technical detail (language, approach, architecture decision)
|
|
176
|
+
- [ ] No links in the body text
|
|
177
|
+
- [ ] Closes with an invitation for feedback, not a call to action
|
|
178
|
+
- [ ] No bullet points or headers
|
|
179
|
+
- [ ] No marketing words: "game-changer", "revolutionary", "powerful", "robust", "seamless", "innovative", "best-in-class", "streamline", "leverage", "transform"
|
|
180
|
+
|
|
181
|
+
If any check fails, fix before presenting.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Step 7: Post to Hacker News (Optional)
|
|
186
|
+
|
|
187
|
+
If `HN_USERNAME` and `HN_PASSWORD` are set in the environment, offer to post directly.
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
echo "HN_USERNAME: ${HN_USERNAME:-not set}"
|
|
191
|
+
echo "HN_PASSWORD: ${HN_PASSWORD:+set (hidden)}"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
If both are set, tell the user: "HN credentials found. Confirm to submit this post directly to Hacker News, or say 'output only' to get the text."
|
|
195
|
+
|
|
196
|
+
On confirmation, run the three-step submission:
|
|
197
|
+
|
|
198
|
+
**Step A: Authenticate and get session cookie**
|
|
199
|
+
```bash
|
|
200
|
+
HN_COOKIE=$(curl -s -c /tmp/hn-cookies.txt -b /tmp/hn-cookies.txt \
|
|
201
|
+
-X POST "https://news.ycombinator.com/login" \
|
|
202
|
+
-d "acct=${HN_USERNAME}&pw=${HN_PASSWORD}&goto=news" \
|
|
203
|
+
-D /tmp/hn-headers.txt \
|
|
204
|
+
-L -o /dev/null -w "%{http_code}")
|
|
205
|
+
|
|
206
|
+
# Verify login succeeded (should redirect to news, not back to login)
|
|
207
|
+
grep -c "user?id=${HN_USERNAME}" /tmp/hn-headers.txt > /dev/null 2>&1 \
|
|
208
|
+
|| curl -s -b /tmp/hn-cookies.txt "https://news.ycombinator.com/" \
|
|
209
|
+
| grep -c "logout" > /dev/null 2>&1 \
|
|
210
|
+
&& echo "Login: success" || echo "Login: failed: check credentials"
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
If login fails: stop. Tell the user their credentials did not work and present the draft for manual submission instead.
|
|
214
|
+
|
|
215
|
+
**Step B: Fetch the submission form to get the CSRF token (fnid)**
|
|
216
|
+
```bash
|
|
217
|
+
FNID=$(curl -s -b /tmp/hn-cookies.txt \
|
|
218
|
+
"https://news.ycombinator.com/submit" \
|
|
219
|
+
| python3 -c "
|
|
220
|
+
import sys, re
|
|
221
|
+
html = sys.stdin.read()
|
|
222
|
+
m = re.search(r'name=\"fnid\" value=\"([^\"]+)\"', html)
|
|
223
|
+
print(m.group(1) if m else 'NOT_FOUND')
|
|
224
|
+
")
|
|
225
|
+
echo "fnid: $FNID"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
If fnid is NOT_FOUND: stop. HN may have changed their form structure. Present the draft for manual submission.
|
|
229
|
+
|
|
230
|
+
**Step C: Submit the post**
|
|
231
|
+
|
|
232
|
+
For a URL submission (project URL):
|
|
233
|
+
```bash
|
|
234
|
+
curl -s -b /tmp/hn-cookies.txt \
|
|
235
|
+
-X POST "https://news.ycombinator.com/r" \
|
|
236
|
+
-d "title={ENCODED_TITLE}&url={ENCODED_URL}&fnid=${FNID}&fnop=submit-page" \
|
|
237
|
+
-D /tmp/hn-submit-headers.txt \
|
|
238
|
+
-L -o /tmp/hn-submit-response.html
|
|
239
|
+
|
|
240
|
+
# Check for success: HN redirects to the post or to newest
|
|
241
|
+
grep -E "item\?id=|/newest" /tmp/hn-submit-headers.txt \
|
|
242
|
+
&& echo "Submission: success" || echo "Submission: check manually"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
For a text post (no URL, just body):
|
|
246
|
+
```bash
|
|
247
|
+
curl -s -b /tmp/hn-cookies.txt \
|
|
248
|
+
-X POST "https://news.ycombinator.com/r" \
|
|
249
|
+
-d "title={ENCODED_TITLE}&text={ENCODED_BODY}&fnid=${FNID}&fnop=submit-page" \
|
|
250
|
+
-D /tmp/hn-submit-headers.txt \
|
|
251
|
+
-L -o /tmp/hn-submit-response.html
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**After submission:**
|
|
255
|
+
1. Extract the post URL from the redirect headers
|
|
256
|
+
2. Tell the user: "Posted: https://news.ycombinator.com/item?id=[ID]"
|
|
257
|
+
3. Remind them: "Reply to comments within the first two hours. Do not reshare the link for 24 hours: HN penalizes vote rings."
|
|
258
|
+
|
|
259
|
+
**If any step fails:** Clean up cookie file (`rm -f /tmp/hn-cookies.txt`) and present the draft for manual submission. Do not retry automatically.
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# Always clean up credentials from disk after the session
|
|
263
|
+
rm -f /tmp/hn-cookies.txt /tmp/hn-headers.txt /tmp/hn-submit-headers.txt /tmp/hn-submit-response.html
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
If `HN_USERNAME` or `HN_PASSWORD` is not set: skip this step entirely and proceed to Step 8.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Step 8: Present Output
|
|
271
|
+
|
|
272
|
+
Present in this order:
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
## Show HN Post
|
|
276
|
+
|
|
277
|
+
### Recommended Title
|
|
278
|
+
Show HN: [title]
|
|
279
|
+
|
|
280
|
+
### Alternative Titles
|
|
281
|
+
1. Show HN: [variant 1]
|
|
282
|
+
2. Show HN: [variant 2]
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
### Body
|
|
287
|
+
|
|
288
|
+
[post body text]
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### Submission Notes
|
|
293
|
+
- URL field: [project URL or GitHub URL]
|
|
294
|
+
- Best time to post: Tuesday to Thursday, 8–10 AM US Eastern
|
|
295
|
+
- After posting: Respond to every comment in the first two hours
|
|
296
|
+
- Do not share the link elsewhere for the first 24 hours: HN flags vote rings
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Do not add commentary about the post. Present the output, then stop.
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "show-hn-writer",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Write a Show HN post for my project. It's called Datasync: it watches a folder and automatically syncs changes to an S3 bucket using a local daemon. I built it because rsync kept breaking on binary files and I needed something that just worked. It's open source, written in Go, free.",
|
|
7
|
+
"expected_output": "Agent reads context, skips Step 1 questions (enough context provided). Drafts three title variants all starting with 'Show HN:'. Recommended title is 60-80 characters. No marketing adjectives. Body opens in first person ('I built...' or 'For the past...'). Body is 150-350 words. Includes technical details (Go, S3, daemon, how it handles binary files). At least one technical decision explained. Closes with feedback invitation, not a CTA. No links in body. Self-QA passes all checks. Output includes three title variants, recommended title, body, and submission notes.",
|
|
8
|
+
"files": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": 2,
|
|
12
|
+
"prompt": "Help me launch on Hacker News. Here's my README: [README with marketing language: 'revolutionary AI-powered platform', 'game-changing productivity boost', 'the future of developer tooling']",
|
|
13
|
+
"expected_output": "Agent reads the README. Detects marketing language in the source material. Drafts title and body without marketing language. Gemini review step flags any remaining adjectives. Self-QA catches 'revolutionary', 'game-changing' if they leaked through. Final output contains none of the original marketing phrases. Title is specific and descriptive. Body explains what the tool actually does technically.",
|
|
14
|
+
"files": ["README.md"]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": 3,
|
|
18
|
+
"prompt": "Write a Show HN for my weekend project. I just made a simple todo app.",
|
|
19
|
+
"expected_output": "Agent recognizes missing context (what makes it technically interesting, why they built this one and not used an existing one, what is different). Asks the 5 required questions before drafting. Does not draft a post based on 'simple todo app' alone: that is not enough to write a good Show HN. After the user provides more context (e.g., 'it uses a CRDT for offline sync'), drafts a specific post about the technical decision, not the generic 'todo app' framing.",
|
|
20
|
+
"files": []
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": 4,
|
|
24
|
+
"prompt": "Write a Show HN title for my project. It's a CLI tool called 'recast' that converts any JSON API response into a typed TypeScript interface.",
|
|
25
|
+
"expected_output": "Agent drafts three title variants. All start with 'Show HN:'. Character counts are shown. Recommended title is the one that most specifically describes what it does. Example acceptable title: 'Show HN: Recast – Generate TypeScript interfaces from any JSON API response' (under 80 chars). No adjectives. No marketing words. En dash (–) used as separator.",
|
|
26
|
+
"files": []
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": 5,
|
|
30
|
+
"prompt": "Write a Show HN post. My project README is attached.",
|
|
31
|
+
"expected_output": "Agent reads README.md. Extracts: what it does, tech stack, motivation. Asks only for information not found in the README (likely: why the builder made it, what makes it technically interesting, current state). Does not ask for information that is available in the file. Drafts complete post using README content plus user answers. Post passes all self-QA checks.",
|
|
32
|
+
"files": ["README.md"]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Show HN Rules and Community Norms
|
|
2
|
+
|
|
3
|
+
## Official Rules
|
|
4
|
+
|
|
5
|
+
- Title must start with exactly "Show HN:": no variation
|
|
6
|
+
- Post in the Show HN comments thread if your submission does not get front page traction
|
|
7
|
+
- Do not ask for upvotes in the post or comments
|
|
8
|
+
- Do not post the same project more than once every few months
|
|
9
|
+
- Must be something you made (or a significant contribution to)
|
|
10
|
+
- Works-in-progress, betas, and experiments are acceptable
|
|
11
|
+
|
|
12
|
+
## What Gets Upvoted
|
|
13
|
+
|
|
14
|
+
Analysis of high-performing Show HN posts:
|
|
15
|
+
|
|
16
|
+
**Strong signals:**
|
|
17
|
+
- Specific technical explanation in the first paragraph of comments
|
|
18
|
+
- Builder responds quickly and in depth to technical questions
|
|
19
|
+
- Unusual technical decision (doing it differently than the standard approach)
|
|
20
|
+
- Honest about limitations and what it does NOT do
|
|
21
|
+
- Clear target audience ("this is for people who...")
|
|
22
|
+
- Open source, or explains why it is not
|
|
23
|
+
|
|
24
|
+
**Weak signals:**
|
|
25
|
+
- "I built this in a weekend" (people stopped caring about this)
|
|
26
|
+
- Vague descriptions ("productivity tool", "developer tool")
|
|
27
|
+
- Screenshots without explanation
|
|
28
|
+
- Body text that reads like a press release
|
|
29
|
+
|
|
30
|
+
## Title Patterns That Work
|
|
31
|
+
|
|
32
|
+
From top Show HN submissions:
|
|
33
|
+
|
|
34
|
+
- Lead with the capability: "Show HN: X – converts Y to Z"
|
|
35
|
+
- Technical specificity: "Show HN: X – builds Y using Z (no Y required)"
|
|
36
|
+
- Comparison as context (use sparingly): "Show HN: X – like [known thing] but for [specific use case]"
|
|
37
|
+
- The honest experiment: "Show HN: X – an experiment in doing Y differently"
|
|
38
|
+
|
|
39
|
+
## Title Patterns That Fail
|
|
40
|
+
|
|
41
|
+
- Adjective overload: "Show HN: X – a fast, simple, powerful tool for Y"
|
|
42
|
+
- Missing the point: "Show HN: I made a website"
|
|
43
|
+
- Marketing speak: "Show HN: The future of developer tooling"
|
|
44
|
+
- Too long: titles over 80 characters get cut off
|
|
45
|
+
|
|
46
|
+
## Body Norms
|
|
47
|
+
|
|
48
|
+
The body is optional but high-performing posts almost always have one.
|
|
49
|
+
|
|
50
|
+
The body is read by people who are already interested (they clicked from the title). Do not re-explain what it does: go deeper. Talk about:
|
|
51
|
+
|
|
52
|
+
- Why you made it instead of using [existing tool]
|
|
53
|
+
- The technical decision you are most proud of or most uncertain about
|
|
54
|
+
- What surprised you during the build
|
|
55
|
+
- What you are still figuring out
|
|
56
|
+
|
|
57
|
+
## Comments Strategy
|
|
58
|
+
|
|
59
|
+
- Respond to every comment on launch day
|
|
60
|
+
- When someone asks a question, answer it thoroughly: do not deflect
|
|
61
|
+
- When someone critiques your approach, acknowledge it honestly
|
|
62
|
+
- If you do not know the answer, say so
|
|
63
|
+
- Never get defensive
|
|
64
|
+
|
|
65
|
+
## Timing
|
|
66
|
+
|
|
67
|
+
- Best time: Tuesday to Thursday, 8-10 AM US Eastern
|
|
68
|
+
- Worst time: Friday afternoon, weekends, major news days
|
|
69
|
+
- The first 2 hours determine front page placement
|
|
70
|
+
- Do not share the link on other platforms until 24 hours after posting (vote rings get flagged)
|
|
71
|
+
|
|
72
|
+
## Resubmission Policy
|
|
73
|
+
|
|
74
|
+
You can repost a significantly updated version of a project. Wait at least 3-6 months. Acknowledge the original post in your new body: "I posted an early version 6 months ago. Here is what changed."
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Show HN Title Formulas
|
|
2
|
+
|
|
3
|
+
## The Core Formula
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Show HN: [Name] – [verb phrase describing what it does]
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The dash is an en dash (–), not a hyphen (-).
|
|
10
|
+
|
|
11
|
+
Total length: 60-80 characters including "Show HN: ".
|
|
12
|
+
|
|
13
|
+
## Five Proven Formats
|
|
14
|
+
|
|
15
|
+
### Format 1: Direct Capability
|
|
16
|
+
```
|
|
17
|
+
Show HN: [Name] – [verb] + [object] + [context]
|
|
18
|
+
```
|
|
19
|
+
Examples:
|
|
20
|
+
- `Show HN: Datasette – Instantly publish SQLite databases to the web`
|
|
21
|
+
- `Show HN: Jitsi – Free, open source video conferencing`
|
|
22
|
+
- `Show HN: Pandoc – Universal document format converter`
|
|
23
|
+
|
|
24
|
+
Best for: tools with a clear, single function
|
|
25
|
+
|
|
26
|
+
### Format 2: Problem-Solution
|
|
27
|
+
```
|
|
28
|
+
Show HN: [Name] – [pain point] without [the annoying part]
|
|
29
|
+
```
|
|
30
|
+
Examples:
|
|
31
|
+
- `Show HN: Zulip – Group chat that threads every conversation`
|
|
32
|
+
- `Show HN: Coolify – Self-hosted Heroku alternative with no vendor lock-in`
|
|
33
|
+
|
|
34
|
+
Best for: tools that replace something people already use but dislike
|
|
35
|
+
|
|
36
|
+
### Format 3: Technical Architecture
|
|
37
|
+
```
|
|
38
|
+
Show HN: [Name] – [what it is] built with [interesting tech choice]
|
|
39
|
+
```
|
|
40
|
+
Examples:
|
|
41
|
+
- `Show HN: Lite XL – A lightweight text editor written in C and Lua`
|
|
42
|
+
- `Show HN: Bun – A fast all-in-one JavaScript runtime built in Zig`
|
|
43
|
+
|
|
44
|
+
Best for: developer tools where the implementation is the interesting part
|
|
45
|
+
|
|
46
|
+
### Format 4: Outcome for Specific User
|
|
47
|
+
```
|
|
48
|
+
Show HN: [Name] – [specific outcome] for [specific person]
|
|
49
|
+
```
|
|
50
|
+
Examples:
|
|
51
|
+
- `Show HN: Fly.io – Deploy app servers close to your users`
|
|
52
|
+
- `Show HN: Retool – Build internal tools in minutes`
|
|
53
|
+
|
|
54
|
+
Best for: B2B tools with a clear target persona
|
|
55
|
+
|
|
56
|
+
### Format 5: The Experiment Frame
|
|
57
|
+
```
|
|
58
|
+
Show HN: [Name] – An experiment in [doing X] differently
|
|
59
|
+
```
|
|
60
|
+
Examples:
|
|
61
|
+
- `Show HN: Ink – React for command-line apps`
|
|
62
|
+
- `Show HN: Tauri – Electron alternative using system webview`
|
|
63
|
+
|
|
64
|
+
Best for: projects that challenge a conventional approach
|
|
65
|
+
|
|
66
|
+
## Character Counting
|
|
67
|
+
|
|
68
|
+
Count characters in your title before submitting:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
title = "Show HN: Datasette – Instantly publish SQLite databases to the web"
|
|
72
|
+
print(f"{len(title)} characters")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Target: 60-80 characters. Under 60 feels thin. Over 80 gets cut off in some views.
|
|
76
|
+
|
|
77
|
+
## Words That Add Length Without Value
|
|
78
|
+
|
|
79
|
+
Remove these from your title:
|
|
80
|
+
- "simple", "easy", "fast", "powerful", "lightweight" (unless it is a literal technical spec like "under 5MB")
|
|
81
|
+
- "tool", "app", "platform", "solution", "service" (usually redundant)
|
|
82
|
+
- "for developers", "for teams" (only include if it narrows the audience usefully)
|
|
83
|
+
- "open source" (put it in the body; the title has no room for it)
|
|
84
|
+
|
|
85
|
+
## En Dash vs Hyphen
|
|
86
|
+
|
|
87
|
+
Always use an en dash (–) as the separator between name and description.
|
|
88
|
+
|
|
89
|
+
Copy it: –
|
|
90
|
+
|
|
91
|
+
Not a hyphen (-) and not an em dash (—).
|
|
92
|
+
|
|
93
|
+
Most Show HN titles follow this convention. It is a visual signal of the format.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Stargazer
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Stargazer is a GitHub star scraper that collects detailed information about users who star a specific repository. It scrapes data like their emails, usernames, names, company names, locations, and social links. While it grabs a full profile, it is primarily designed to find and verify user emails.
|
|
6
|
+
|
|
7
|
+
It outperforms standard scrapers by implementing a multi-tier verification system that filters out false positives, specifically those originating from repository forks (e.g., stopping the scraper from accidentally pulling a famous developer's email just because a user forked their repository).
|
|
8
|
+
|
|
9
|
+
https://github.com/user-attachments/assets/1e15a51b-8bff-4282-928e-fc99da2343cb
|
|
10
|
+
|
|
11
|
+
## The 5-Tier Extraction Architecture
|
|
12
|
+
|
|
13
|
+
This system uses five distinct methods to find and verify user emails, ensuring maximum coverage and accuracy:
|
|
14
|
+
|
|
15
|
+
1. **Profile API**: Direct extraction from the public GitHub user profile.
|
|
16
|
+
2. **Events API**: Analysis of recent user activity and public event streams to find associated email addresses.
|
|
17
|
+
3. **GPG Keys**: Extraction of email identities linked to verified GPG keys on the user account.
|
|
18
|
+
4. **Patch Regex**: Deep scanning of commit patches and diffs using regular expressions to identify author emails.
|
|
19
|
+
5. **Global Search API**: Advanced search queries with cryptographic login verification to find user mentions across the platform.
|
|
20
|
+
|
|
21
|
+
## Key Features
|
|
22
|
+
|
|
23
|
+
* **Multi-Token Rotation**: Supports a pool of GitHub Personal Access Tokens to distribute requests and maximize speed.
|
|
24
|
+
* **Smart Rate Limiting**: Uses semaphores to manage concurrency and bypass the standard 30 requests per minute search limit safely.
|
|
25
|
+
* **JSONL Checkpointing**: Saves progress in real-time using JSON Lines format, allowing for easy resumption if your internet drops or the script is stopped.
|
|
26
|
+
* **Jitter**: Implements randomized delays between requests to mimic human behavior and avoid GitHub abuse detection.
|
|
27
|
+
* **CSV Generation**: Includes built-in tools to transform raw extraction data into clean, structured CSV files for marketing or analysis.
|
|
28
|
+
|
|
29
|
+
## How to get a GitHub Personal Access Token (PAT)
|
|
30
|
+
|
|
31
|
+
To run the scraper, you will need at least one GitHub Personal Access Token (though 3 or more are recommended for repositories with thousands of stars).
|
|
32
|
+
|
|
33
|
+
1. Go to your GitHub Token Settings: https://github.com/settings/tokens
|
|
34
|
+
2. Click **Generate new token (classic)**.
|
|
35
|
+
3. Give it a descriptive note (e.g., "Stargazer Scraper").
|
|
36
|
+
4. Under scopes, select **`read:user`** and **`user:email`**. This allows the script to read public profile data and emails. No other permissions are required.
|
|
37
|
+
5. Scroll down and click **Generate token**.
|
|
38
|
+
6. Copy the `ghp_...` string and paste it into your `.env` file.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
1. Clone the repository to your local machine.
|
|
43
|
+
2. Install the required dependencies using pip:
|
|
44
|
+
```bash
|
|
45
|
+
pip install aiohttp python-dotenv
|
|
46
|
+
```
|
|
47
|
+
3. Create a `.env` file in the root directory. You can use `stargazer-skill/assets/.env.example` as a template.
|
|
48
|
+
|
|
49
|
+
## Configuration
|
|
50
|
+
|
|
51
|
+
Edit the `.env` file with your specific settings:
|
|
52
|
+
|
|
53
|
+
* `GITHUB_PATS`: A comma-separated list of your GitHub Personal Access Tokens.
|
|
54
|
+
* `TARGET_OWNER`: The username or organization that owns the repository.
|
|
55
|
+
* `TARGET_REPO`: The name of the repository to scan.
|
|
56
|
+
* `MAX_USERS`: The maximum number of stargazers to process.
|
|
57
|
+
* `MAX_CONCURRENT`: The number of concurrent requests to run (50 is recommended).
|
|
58
|
+
|
|
59
|
+
## Usage Guide
|
|
60
|
+
|
|
61
|
+
Run the extraction process in three sequential steps.
|
|
62
|
+
|
|
63
|
+
### 1. Extract Data
|
|
64
|
+
Start the main extraction script to gather detailed user information.
|
|
65
|
+
```bash
|
|
66
|
+
python stargazer-skill/scripts/stargazer_deep_extractor.py
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Count Results
|
|
70
|
+
Analyze the extracted data to see how many unique emails were found. You can run this while the main script is running.
|
|
71
|
+
```bash
|
|
72
|
+
python stargazer-skill/scripts/count_emails.py
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 3. Convert to CSV
|
|
76
|
+
Generate a final CSV file for use in other applications.
|
|
77
|
+
```bash
|
|
78
|
+
python stargazer-skill/scripts/convert_to_csv.py
|
|
79
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stargazer-deep-extractor
|
|
3
|
+
description: Advanced 5-tier OSINT scraper for extracting GitHub stargazer emails. Use this skill when a user wants to scrape, extract, or download stargazers from a GitHub repository.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Stargazer Deep Extractor Skill
|
|
7
|
+
|
|
8
|
+
This skill provides a highly detailed, script-like workflow for an AI Agent to extract GitHub stargazers and their email addresses. It leverages the 5-tier Stargazer Deep Extractor toolkit (Profile API, PushEvents, GPG Keys, Patch Regex, and Global Search API) to maximize extraction yields while bypassing rate limits through multi-token rotation and asyncio semaphores.
|
|
9
|
+
|
|
10
|
+
## Tone and Formatting Constraints
|
|
11
|
+
- You must adopt a strictly professional, technical tone.
|
|
12
|
+
- Do not use emojis in your responses.
|
|
13
|
+
- Do not use em-dashes (use standard hyphens or colons instead).
|
|
14
|
+
|
|
15
|
+
## Workflow Execution Steps
|
|
16
|
+
|
|
17
|
+
### Step 1: Input Validation and Extraction
|
|
18
|
+
When a user requests a repository scrape, you must extract the exact GitHub owner and repository name.
|
|
19
|
+
- For a URL like `https://github.com/openai/codex`, the owner is `openai` and the repository is `codex`.
|
|
20
|
+
- If the user only provides `openai/codex`, split it by the slash.
|
|
21
|
+
- If the repository name is not provided, you must ask the user for it.
|
|
22
|
+
|
|
23
|
+
### Step 2: Interrogation and Environment Setup
|
|
24
|
+
If the user is running this for the first time, you must interrogate them to set up the `.env` file correctly. Ask the following questions in a point-wise format:
|
|
25
|
+
1. "What is the maximum number of stargazers you would like to scrape? By default, this will be the total star count of the repository."
|
|
26
|
+
2. "Please provide your GitHub Personal Access Tokens (PATs) as a comma-separated list."
|
|
27
|
+
|
|
28
|
+
### Step 3: Token Requirement Notice
|
|
29
|
+
You must remind the user about GitHub's strict rate limits and recommend the optimal number of tokens based on the repository's size.
|
|
30
|
+
Provide the following advisory notice to the user:
|
|
31
|
+
- Less than 2,000 stars: 1 token is generally sufficient.
|
|
32
|
+
- 2,000 to 5,000 stars: 2 to 3 tokens are recommended.
|
|
33
|
+
- More than 20,000 stars: 4 or more tokens are strongly recommended.
|
|
34
|
+
|
|
35
|
+
**CRITICAL RULE**: Do not hard code this token math as a mandatory constraint. You must deliver this as a notice or recommendation. If the user decides not to follow the advice and wants to proceed with fewer tokens, you must allow them to do so and proceed with whatever they provide. Let the user use whatever they want.
|
|
36
|
+
|
|
37
|
+
### Step 4: Configuration Editing
|
|
38
|
+
After gathering the user's responses, you must configure the `.env` file in the execution directory (referencing `assets/.env.example` if needed).
|
|
39
|
+
Ensure the following variables are written to `.env`:
|
|
40
|
+
- `GITHUB_PATS`: Comma-separated list of the user's tokens.
|
|
41
|
+
- `TARGET_OWNER`: The parsed repository owner.
|
|
42
|
+
- `TARGET_REPO`: The parsed repository name.
|
|
43
|
+
- `MAX_USERS`: The user's defined limit (or the total star count).
|
|
44
|
+
- `MAX_CONCURRENT`: Set to 50 for optimal performance.
|
|
45
|
+
|
|
46
|
+
### Step 5: Sequence Execution
|
|
47
|
+
You must run the bundled scripts in the exact sequence below using the Bash tool. The JSONL checkpointing system ensures that if the process is interrupted, it can resume without losing data.
|
|
48
|
+
|
|
49
|
+
1. **Deep Extraction**: Run `python scripts/stargazer_deep_extractor.py`. This executes the 5-tier OSINT extraction.
|
|
50
|
+
2. **Real-time Statistics**: Run `python scripts/count_emails.py`. This analyzes the generated JSONL file (`{TARGET_OWNER}_{TARGET_REPO}_detailed.jsonl`) to count the exact number of emails successfully found vs. null emails.
|
|
51
|
+
3. **CSV Conversion**: Run `python scripts/convert_to_csv.py`. This converts the final JSONL data into a structured CSV file with proper `utf-8-sig` encoding for Excel compatibility.
|
|
52
|
+
|
|
53
|
+
### Step 6: Final Transparency Report
|
|
54
|
+
After the sequence completes, you must be fully transparent with the user. Provide a final summary reporting:
|
|
55
|
+
- The total number of people fetched.
|
|
56
|
+
- The exact total of emails successfully extracted.
|
|
57
|
+
- The total number of null (hidden) emails.
|
|
58
|
+
- The absolute path to the final CSV deliverable.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Add your GitHub Personal Access Tokens here
|
|
2
|
+
# Separate multiple tokens with commas for rotation (e.g. ghp_xyz,ghp_abc)
|
|
3
|
+
GITHUB_PATS="ghp_token1,ghp_token2,ghp_token3,ghp_token4,ghp_token5"
|
|
4
|
+
|
|
5
|
+
# Set the target repository here
|
|
6
|
+
TARGET_OWNER="openai"
|
|
7
|
+
TARGET_REPO="codex"
|
|
8
|
+
|
|
9
|
+
# ----------------------------------------
|
|
10
|
+
# SCALING OPTIONS (ENTERPRISE SETTINGS)
|
|
11
|
+
# ----------------------------------------
|
|
12
|
+
|
|
13
|
+
# STOP SCRAPING AT EXACTLY THIS MANY STARGAZERS
|
|
14
|
+
MAX_USERS=25000
|
|
15
|
+
|
|
16
|
+
# CONCURRENCY: How many users to process concurrently (Continuous Stream)
|
|
17
|
+
# Higher = Faster, but might trigger secondary GitHub abuse limits. 50 is a safe maximum.
|
|
18
|
+
MAX_CONCURRENT=50
|