@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,271 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reddit-icp-monitor
|
|
3
|
+
description: Watches subreddits for people describing the exact problem you solve, scores their relevance to your ICP, and drafts a helpful non-spammy reply for each high-signal post. Use when asked to monitor Reddit for ICP signals, find prospects on Reddit, surface pain point posts, draft helpful Reddit replies, or scan subreddits for buying signals. Trigger when a user says "monitor Reddit for my ICP", "find people on Reddit who need my product", "scan subreddits for pain points", "draft Reddit replies for prospects", or "check Reddit for buying signals".
|
|
4
|
+
compatibility: [claude-code, gemini-cli, github-copilot]
|
|
5
|
+
author: OpenDirectory
|
|
6
|
+
version: 1.0.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Reddit ICP Monitor
|
|
10
|
+
|
|
11
|
+
Watch subreddits for people describing the problem you solve. Score their relevance. Draft a helpful reply for each match.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
**Critical rule:** Never invent post URLs, titles, or content. Every post in the output must come from a Reddit search result. Mark any section with no results as "No matches found." Never draft a reply to a post that was not returned by the search.
|
|
16
|
+
|
|
17
|
+
**Anti-spam rule:** Drafted replies must never mention your product or company name unless the post explicitly asks for tool recommendations. Sound like a practitioner, not a marketer.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Step 1: Setup Check
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+set}"
|
|
25
|
+
echo "REDDIT_CLIENT_ID: ${REDDIT_CLIENT_ID:-not set, using public endpoints (10 RPM)}"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**If GEMINI_API_KEY is missing:**
|
|
29
|
+
Stop. Tell the user: "GEMINI_API_KEY is required. Get it at aistudio.google.com. Add it to your .env file."
|
|
30
|
+
|
|
31
|
+
**If Reddit credentials are missing:**
|
|
32
|
+
Continue. Use Reddit's public JSON endpoints (no auth required, 10 RPM limit). For most monitoring sessions of 3-6 subreddit searches, this is sufficient.
|
|
33
|
+
|
|
34
|
+
**If REDDIT_CLIENT_ID is set:**
|
|
35
|
+
Use OAuth for 60 RPM. Fetch a token first:
|
|
36
|
+
```bash
|
|
37
|
+
TOKEN=$(curl -s -X POST \
|
|
38
|
+
-d "grant_type=password&username=$REDDIT_USERNAME&password=$REDDIT_PASSWORD" \
|
|
39
|
+
--user "$REDDIT_CLIENT_ID:$REDDIT_CLIENT_SECRET" \
|
|
40
|
+
-H "User-Agent: varnan-skills/1.0" \
|
|
41
|
+
https://www.reddit.com/api/v1/access_token \
|
|
42
|
+
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
|
|
43
|
+
```
|
|
44
|
+
Use `Authorization: Bearer $TOKEN` and `https://oauth.reddit.com` base URL for all subsequent requests.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Step 2: Load ICP
|
|
49
|
+
|
|
50
|
+
Check for an existing ICP file:
|
|
51
|
+
```bash
|
|
52
|
+
ls docs/icp.md 2>/dev/null && echo "icp found" || echo "icp missing"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**If docs/icp.md exists:** Read it. Extract:
|
|
56
|
+
- `product`: one-sentence product description
|
|
57
|
+
- `pain_points`: list of pain point phrases (exact buyer language)
|
|
58
|
+
- `anti_keywords`: phrases that disqualify a post
|
|
59
|
+
- `subreddits`: list of subreddits to search
|
|
60
|
+
|
|
61
|
+
**If docs/icp.md does not exist:** Ask these 3 questions. Do not proceed until all 3 are answered:
|
|
62
|
+
1. What does your product do? (one sentence)
|
|
63
|
+
2. What subreddits does your ICP post in? (comma-separated, e.g. devops, startups, SaaS)
|
|
64
|
+
3. What pain point phrases should trigger a match? (3-5 phrases in your buyer's own words, e.g. "onboarding takes forever", "can't see why users churn")
|
|
65
|
+
|
|
66
|
+
After answers are collected, save to docs/icp.md in the canonical format from `references/icp-format.md`. Confirm: "ICP saved to docs/icp.md. It will be used automatically in future runs."
|
|
67
|
+
|
|
68
|
+
Read `references/icp-format.md` for the canonical format and examples of good vs bad pain point phrases.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Step 3: Search Reddit
|
|
73
|
+
|
|
74
|
+
For each combination of subreddit and pain point phrase, run one search. Use public endpoints unless OAuth credentials are set.
|
|
75
|
+
|
|
76
|
+
**Without OAuth (public endpoint):**
|
|
77
|
+
```bash
|
|
78
|
+
curl -s \
|
|
79
|
+
-H "User-Agent: varnan-skills/1.0" \
|
|
80
|
+
"https://www.reddit.com/r/{SUBREDDIT}/search.json?q={PHRASE}&sort=new&t=week&limit=25&restrict_sr=true" \
|
|
81
|
+
| python3 -c "
|
|
82
|
+
import sys, json
|
|
83
|
+
d = json.load(sys.stdin)
|
|
84
|
+
posts = d.get('data', {}).get('children', [])
|
|
85
|
+
for p in posts:
|
|
86
|
+
data = p['data']
|
|
87
|
+
print(json.dumps({
|
|
88
|
+
'id': data['id'],
|
|
89
|
+
'title': data['title'],
|
|
90
|
+
'body': data.get('selftext', '')[:600],
|
|
91
|
+
'url': 'https://reddit.com' + data['permalink'],
|
|
92
|
+
'score': data['score'],
|
|
93
|
+
'comments': data['num_comments'],
|
|
94
|
+
'subreddit': data['subreddit'],
|
|
95
|
+
'created_utc': data['created_utc']
|
|
96
|
+
}))
|
|
97
|
+
"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**With OAuth:**
|
|
101
|
+
Replace `https://www.reddit.com` with `https://oauth.reddit.com` and add `-H "Authorization: Bearer $TOKEN"`.
|
|
102
|
+
|
|
103
|
+
**URL-encode the phrase** before inserting into the query string:
|
|
104
|
+
```bash
|
|
105
|
+
ENCODED=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" "{PHRASE}")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Time window defaults:**
|
|
109
|
+
- Default: `t=week` (last 7 days)
|
|
110
|
+
- User says "today" or "last 24 hours": `t=day`
|
|
111
|
+
- User says "this month": `t=month`
|
|
112
|
+
|
|
113
|
+
**After all searches:**
|
|
114
|
+
- Collect all posts into one list
|
|
115
|
+
- Deduplicate by post ID. If the same post matches multiple phrases, keep it once and note all matching phrases.
|
|
116
|
+
- If a search returns 0 posts: note it and continue. Do not stop.
|
|
117
|
+
|
|
118
|
+
State the total candidate count before scoring: "Found X candidate posts across Y subreddits."
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Step 4: Score Relevance with Gemini
|
|
123
|
+
|
|
124
|
+
Write all candidate posts and the ICP context to a temp file, then score:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
cat > /tmp/reddit-score-request.json << 'ENDJSON'
|
|
128
|
+
{
|
|
129
|
+
"system_instruction": {
|
|
130
|
+
"parts": [{
|
|
131
|
+
"text": "You are a GTM analyst identifying Reddit posts where someone is experiencing the exact pain point that a specific product solves. For each post provided, output a JSON object with these fields: id (the post id), score (integer 1-5), reason (one sentence explaining the score). Scoring rubric: 5 = person clearly has the problem AND is actively seeking help or venting frustration about it; 4 = strong signal, problem is present but less explicit; 3 = possible match, uncertain; 2 = tangentially related but not the core pain; 1 = unrelated. Output only a JSON array of score objects. No commentary before or after the array."
|
|
132
|
+
}]
|
|
133
|
+
},
|
|
134
|
+
"contents": [{
|
|
135
|
+
"parts": [{
|
|
136
|
+
"text": "POSTS_AND_ICP_CONTEXT_HERE"
|
|
137
|
+
}]
|
|
138
|
+
}],
|
|
139
|
+
"generationConfig": {
|
|
140
|
+
"temperature": 0.2,
|
|
141
|
+
"maxOutputTokens": 2048
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
ENDJSON
|
|
145
|
+
curl -s -X POST \
|
|
146
|
+
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
|
|
147
|
+
-H "Content-Type: application/json" \
|
|
148
|
+
-d @/tmp/reddit-score-request.json \
|
|
149
|
+
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Replace `POSTS_AND_ICP_CONTEXT_HERE` with:
|
|
153
|
+
- The product description and pain point phrases from Step 2
|
|
154
|
+
- Each candidate post: id, title, body snippet
|
|
155
|
+
- Anti-keywords from the ICP (Gemini should score these lower)
|
|
156
|
+
|
|
157
|
+
Keep only posts with score >= 4 for response drafting.
|
|
158
|
+
|
|
159
|
+
State: "X posts scored 4 or 5. Drafting replies."
|
|
160
|
+
|
|
161
|
+
If 0 posts score >= 4: output the zero-results message from Step 7 and stop. Do not draft empty replies.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Step 5: Draft Replies with Gemini
|
|
166
|
+
|
|
167
|
+
Read `references/reply-rules.md` before drafting. Determine the post type for each high-scoring post (Mode 1, 2, or 3) and pass the mode to Gemini.
|
|
168
|
+
|
|
169
|
+
For each post scoring >= 4, draft a reply (maximum 5 replies per session):
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
cat > /tmp/reddit-reply-request.json << 'ENDJSON'
|
|
173
|
+
{
|
|
174
|
+
"system_instruction": {
|
|
175
|
+
"parts": [{
|
|
176
|
+
"text": "You are a practitioner who has personally solved the exact problem being described in this Reddit post. Write a helpful reply that: (1) directly addresses what the person asked or is frustrated about, (2) shares a specific, useful insight from real experience, (3) does NOT mention any product, tool, or company by name unless the post explicitly asks for tool recommendations, (4) is 2-5 sentences, written in plain conversational prose with no headers or bullet lists, (5) optionally ends with a low-pressure invitation to continue the conversation. Do not use marketing language. Do not use these words: game-changer, best-in-class, streamline, transform, revolutionize, leverage, seamless, robust, comprehensive, innovative. Sound like a real person."
|
|
177
|
+
}]
|
|
178
|
+
},
|
|
179
|
+
"contents": [{
|
|
180
|
+
"parts": [{
|
|
181
|
+
"text": "POST_CONTENT_AND_MODE_HERE"
|
|
182
|
+
}]
|
|
183
|
+
}],
|
|
184
|
+
"generationConfig": {
|
|
185
|
+
"temperature": 0.7,
|
|
186
|
+
"maxOutputTokens": 512
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
ENDJSON
|
|
190
|
+
curl -s -X POST \
|
|
191
|
+
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
|
|
192
|
+
-H "Content-Type: application/json" \
|
|
193
|
+
-d @/tmp/reddit-reply-request.json \
|
|
194
|
+
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Replace `POST_CONTENT_AND_MODE_HERE` with:
|
|
198
|
+
- The full post title and body
|
|
199
|
+
- The reply mode (Mode 1: venting/frustration, Mode 2: how-do-you-handle-X, Mode 3: tool recommendation)
|
|
200
|
+
- The product description (so Gemini knows what to avoid naming in Mode 1/2)
|
|
201
|
+
- If Mode 3: Gemini may name the product AND must name one alternative
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Step 6: Self-QA
|
|
206
|
+
|
|
207
|
+
Run every check and fix violations before presenting:
|
|
208
|
+
|
|
209
|
+
- [ ] No product name in any Mode 1 or Mode 2 reply
|
|
210
|
+
- [ ] No banned words in any reply: "game-changer", "best-in-class", "streamline", "transform", "revolutionize", "leverage", "seamless", "robust", "innovative"
|
|
211
|
+
- [ ] Every reply is 2-5 sentences (count and state)
|
|
212
|
+
- [ ] Each reply directly addresses the specific question or frustration in the post
|
|
213
|
+
- [ ] All URLs in the output are real Reddit URLs from the search results (not constructed or guessed)
|
|
214
|
+
- [ ] No more than 5 replies drafted in total
|
|
215
|
+
- [ ] Mode 3 replies mention at least one alternative (not just the product)
|
|
216
|
+
- [ ] If any subreddit returned 0 results across all keyword searches, flag it in the output
|
|
217
|
+
|
|
218
|
+
Fix any violation before presenting.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Step 7: Output and Save
|
|
223
|
+
|
|
224
|
+
Present the full report:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
## Reddit ICP Monitor — [YYYY-MM-DD]
|
|
228
|
+
|
|
229
|
+
**Subreddits monitored:** r/[subreddit1], r/[subreddit2]
|
|
230
|
+
**Time window:** Last 7 days
|
|
231
|
+
**Keywords searched:** [phrase1], [phrase2], [phrase3]
|
|
232
|
+
**Candidates found:** X posts
|
|
233
|
+
**High-signal matches (score 4-5):** Y posts
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### Match 1 — Score [N]/5
|
|
238
|
+
**Post:** [title](url)
|
|
239
|
+
**Subreddit:** r/[subreddit] | [N] upvotes | [N] comments
|
|
240
|
+
**Signal quote:** "[relevant excerpt from post body]"
|
|
241
|
+
**Matched keyword:** [phrase]
|
|
242
|
+
**Post type:** Mode [1/2/3]
|
|
243
|
+
|
|
244
|
+
**Drafted reply:**
|
|
245
|
+
[reply text]
|
|
246
|
+
|
|
247
|
+
**Reply word count:** N words
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
[repeat for each match]
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
**Subreddits with 0 results:** [list any that returned nothing]
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**If 0 posts scored >= 4:**
|
|
259
|
+
"No high-signal matches found in the last 7 days across [subreddits]. Keywords searched: [list]. Try widening the time window (run again and say 'last month') or broadening your pain point phrases in docs/icp.md."
|
|
260
|
+
|
|
261
|
+
**Save to file:**
|
|
262
|
+
```bash
|
|
263
|
+
mkdir -p docs/reddit-intel
|
|
264
|
+
OUTFILE="docs/reddit-intel/$(date +%Y-%m-%d).md"
|
|
265
|
+
cat > "$OUTFILE" << 'EOF'
|
|
266
|
+
REPORT_CONTENT_HERE
|
|
267
|
+
EOF
|
|
268
|
+
echo "Saved to $OUTFILE"
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "reddit-icp-monitor",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Monitor Reddit for my ICP. My docs/icp.md is already set up with subreddits: devops, startups. Pain points: 'onboarding takes forever', 'new hire ramp time too long'. Product: Ramp, a sales onboarding platform.",
|
|
7
|
+
"expected_output": "Agent checks GEMINI_API_KEY (set). No Reddit credentials set; uses public JSON endpoints. Reads docs/icp.md, extracts subreddits and pain points. Runs 4 searches (2 subreddits x 2 phrases), URL-encodes each phrase. Deduplicates results by post ID. Writes candidate posts to /tmp/reddit-score-request.json, calls Gemini at temperature 0.2 for scoring. Keeps posts with score >= 4. Drafts replies for high-scoring posts using Gemini at temperature 0.7. Self-QA confirms no product name in Mode 1 or Mode 2 replies, no banned words, all replies 2-5 sentences. Saves report to docs/reddit-intel/YYYY-MM-DD.md.",
|
|
8
|
+
"files": [
|
|
9
|
+
"docs/icp.md"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": 2,
|
|
14
|
+
"prompt": "Run the Reddit ICP monitor.",
|
|
15
|
+
"expected_output": "Agent checks GEMINI_API_KEY (set). Checks for docs/icp.md (not found). Asks all 3 questions in order before proceeding: (1) product description, (2) subreddits, (3) pain point phrases. Does not run any searches before all 3 questions are answered. After answers collected, saves to docs/icp.md in canonical YAML format (product, personas, pain_points, anti_keywords, subreddits). Confirms: 'ICP saved to docs/icp.md.' Proceeds with full search, score, draft cycle. Saves report to docs/reddit-intel/YYYY-MM-DD.md.",
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 3,
|
|
20
|
+
"prompt": "Check Reddit for ICP signals from this week.",
|
|
21
|
+
"expected_output": "Agent detects GEMINI_API_KEY is missing from environment. Stops immediately at Step 1. Tells the user: 'GEMINI_API_KEY is required. Get it at aistudio.google.com. Add it to your .env file.' Does not run any Reddit searches or generate any content.",
|
|
22
|
+
"files": [],
|
|
23
|
+
"setup": "GEMINI_API_KEY not set in environment"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": 4,
|
|
27
|
+
"prompt": "Monitor Reddit for ICP signals. Subreddits: r/devops, r/startups. Pain points: 'kubernetes cluster management', 'helm chart complexity'.",
|
|
28
|
+
"expected_output": "Agent runs all searches across both subreddits and both keywords (4 total searches). All searches return 0 results. Agent does not error or produce empty drafted replies. Output: 'No high-signal matches found in the last 7 days across r/devops, r/startups. Keywords searched: kubernetes cluster management, helm chart complexity. Try widening the time window (run again and say last month) or broadening your pain point phrases in docs/icp.md.' Does not attempt to draft replies for zero candidates.",
|
|
29
|
+
"files": []
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": 5,
|
|
33
|
+
"prompt": "Monitor Reddit for my ICP. Mode 2 post found: 'How does your team handle documentation that always goes stale? Looking for process advice.' Product is described in docs/icp.md as DocSync, a docs-as-code platform.",
|
|
34
|
+
"expected_output": "Agent scores the post >= 4 (clear operational pain point matching the ICP). Classifies post as Mode 2 (how-do-you-handle-X). Drafts a reply describing a process or approach without naming DocSync. Self-QA step detects the word 'DocSync' in the drafted reply. Agent revises the reply to remove the product name. Presents the revised reply which describes the approach generically ('we treat docs as a release artifact, not a side task') without naming any product. Word count confirmed 2-5 sentences.",
|
|
35
|
+
"files": [
|
|
36
|
+
"docs/icp.md"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# ICP Format
|
|
2
|
+
|
|
3
|
+
Rules for defining a good ICP for Reddit monitoring and the canonical docs/icp.md format.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What Makes a Good Pain Point Phrase
|
|
8
|
+
|
|
9
|
+
Pain point phrases are the most important input. Weak phrases return noise. Strong phrases surface exactly the posts you want.
|
|
10
|
+
|
|
11
|
+
**Write in first-person buyer language, not product marketing language.**
|
|
12
|
+
|
|
13
|
+
Good phrases match what someone would actually type when frustrated:
|
|
14
|
+
- "onboarding takes forever"
|
|
15
|
+
- "can't figure out why users are churning"
|
|
16
|
+
- "new hire ramp time is killing us"
|
|
17
|
+
- "docs are always out of date"
|
|
18
|
+
- "deployment takes hours"
|
|
19
|
+
- "can't reproduce what's in production"
|
|
20
|
+
|
|
21
|
+
Bad phrases use category language your ICP would never use:
|
|
22
|
+
- "needs better developer productivity tooling"
|
|
23
|
+
- "seeks churn reduction solution"
|
|
24
|
+
- "looking for CI/CD pipeline optimization"
|
|
25
|
+
- "wants improved observability platform"
|
|
26
|
+
|
|
27
|
+
**3-6 phrases is the right range.** Too few and you miss signals. Too many and you flood the results with weak matches.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## What Makes a Good Subreddit Choice
|
|
32
|
+
|
|
33
|
+
Choose subreddits where your ICP goes to ask questions, not where they discuss your product category.
|
|
34
|
+
|
|
35
|
+
Good subreddits (where people describe problems):
|
|
36
|
+
- r/devops — engineers asking "how do you handle X" and venting about ops problems
|
|
37
|
+
- r/ExperiencedDevs — senior engineers sharing pain points
|
|
38
|
+
- r/startups — founders discussing GTM, ops, and scaling problems
|
|
39
|
+
- r/SaaS — SaaS founders and operators discussing growth problems
|
|
40
|
+
- r/entrepreneurship — early-stage founders venting and asking for advice
|
|
41
|
+
- r/sysadmin — ops teams discussing tooling and workflow pain
|
|
42
|
+
|
|
43
|
+
Bad subreddits (noise, not signal):
|
|
44
|
+
- r/programming — too broad, technical discussions not pain points
|
|
45
|
+
- r/technology — consumer focus, not B2B
|
|
46
|
+
- r/MachineLearning — research-focused, not operational pain
|
|
47
|
+
- Your product's own subreddit — not monitoring your own community
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Anti-Keywords
|
|
52
|
+
|
|
53
|
+
Anti-keywords reduce false positives. If a post contains an anti-keyword, Gemini scores it lower.
|
|
54
|
+
|
|
55
|
+
Common anti-keyword categories:
|
|
56
|
+
- Company size disqualifiers: "enterprise", "Fortune 500", "10,000 employees"
|
|
57
|
+
- Platform disqualifiers: "SAP", "Oracle", "Salesforce Enterprise"
|
|
58
|
+
- Competitor-specific: add your main competitor if their users are not your ICP
|
|
59
|
+
- Geographic disqualifiers: "government", "regulated industry", "HIPAA-only" (if you don't serve those)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Canonical docs/icp.md Format
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
---
|
|
67
|
+
product: "One sentence: what the product does and who it's for."
|
|
68
|
+
personas:
|
|
69
|
+
- "Job title, company size, industry (e.g. VP Engineering, 50-200 person B2B SaaS)"
|
|
70
|
+
- "Job title, company size, industry (add more if needed)"
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
pain_points:
|
|
74
|
+
- "exact phrase your ICP uses when they have the problem"
|
|
75
|
+
- "another phrase — keep it first-person and conversational"
|
|
76
|
+
- "third phrase"
|
|
77
|
+
- "fourth phrase (optional)"
|
|
78
|
+
- "fifth phrase (optional)"
|
|
79
|
+
|
|
80
|
+
anti_keywords:
|
|
81
|
+
- "enterprise"
|
|
82
|
+
- "government"
|
|
83
|
+
- "add more if needed"
|
|
84
|
+
|
|
85
|
+
subreddits:
|
|
86
|
+
- devops
|
|
87
|
+
- ExperiencedDevs
|
|
88
|
+
- startups
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Rules:**
|
|
92
|
+
- `product` must be one sentence. The agent passes this to Gemini for scoring context.
|
|
93
|
+
- `pain_points` must be in quotes. Each is passed as a Reddit search query.
|
|
94
|
+
- `subreddits` are bare names without the `r/` prefix.
|
|
95
|
+
- The file is saved automatically after the first run if it does not exist.
|
|
96
|
+
- Edit it directly to refine keywords based on what you find.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Worked Example
|
|
101
|
+
|
|
102
|
+
For a sales onboarding platform targeting VP Sales at B2B SaaS companies:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
---
|
|
106
|
+
product: "Ramp helps B2B SaaS sales teams cut new hire time-to-first-deal by replacing ad hoc onboarding with structured playbooks and live deal coaching."
|
|
107
|
+
personas:
|
|
108
|
+
- "VP Sales, 50-200 person B2B SaaS company"
|
|
109
|
+
- "Head of Revenue, Series B startup"
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
pain_points:
|
|
113
|
+
- "new rep ramp time too long"
|
|
114
|
+
- "sales onboarding is a mess"
|
|
115
|
+
- "new hires aren't hitting quota"
|
|
116
|
+
- "onboarding takes 90 days"
|
|
117
|
+
- "reps forget what they learned in training"
|
|
118
|
+
|
|
119
|
+
anti_keywords:
|
|
120
|
+
- "enterprise"
|
|
121
|
+
- "government"
|
|
122
|
+
- "channel sales"
|
|
123
|
+
|
|
124
|
+
subreddits:
|
|
125
|
+
- sales
|
|
126
|
+
- SaaS
|
|
127
|
+
- startups
|
|
128
|
+
- EntrepreneurRideAlong
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Subreddits to avoid for this product: r/cscareerquestions (job seekers, not managers), r/sales (mostly individual contributors, not VPs).
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Reply Rules
|
|
2
|
+
|
|
3
|
+
Three modes for drafted replies. Hard rules that apply to all modes.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Three Post Types
|
|
8
|
+
|
|
9
|
+
Every Reddit post that scores >= 4 falls into one of three modes. The mode determines what the reply can and cannot include.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### Mode 1 — Venting or Frustration Post
|
|
14
|
+
|
|
15
|
+
The person is expressing frustration, not asking for help or recommendations. They want to be heard.
|
|
16
|
+
|
|
17
|
+
**Signals:** Statements like "I'm so frustrated with X", "Why is Y so hard?", "Nobody talks about how broken Z is."
|
|
18
|
+
|
|
19
|
+
**Reply approach:**
|
|
20
|
+
- Start by validating the pain. Show you understand why it's hard.
|
|
21
|
+
- Share one specific insight from your own experience that adds something useful.
|
|
22
|
+
- Do NOT suggest solutions, tools, or products.
|
|
23
|
+
- Do NOT ask "have you tried X?"
|
|
24
|
+
- End with an optional empathetic close or invitation: "If it helps to know, this is a common ceiling at your scale."
|
|
25
|
+
|
|
26
|
+
**Example:**
|
|
27
|
+
Post: "Why is onboarding new engineers so painful? We hire 4 people a month and it takes 3 weeks before they touch anything real."
|
|
28
|
+
|
|
29
|
+
Reply: "This is one of those problems that gets worse exactly as you're succeeding — 4 hires a month means your onboarding overhead compounds faster than your headcount. Most teams don't notice until a quarter where ramp time visibly affected bookings. The thing that usually helps isn't a tool, it's admitting the informal 'follow a senior dev' approach doesn't scale past 10 people."
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
### Mode 2 — "How do you handle X?" Post
|
|
34
|
+
|
|
35
|
+
The person is asking how other teams or practitioners approach a problem. They want operational advice.
|
|
36
|
+
|
|
37
|
+
**Signals:** Questions like "How does your team handle X?", "What does your process look like for Y?", "Anyone else dealing with Z — what did you do?"
|
|
38
|
+
|
|
39
|
+
**Reply approach:**
|
|
40
|
+
- Describe what you or your team actually does, in operational terms.
|
|
41
|
+
- Include one concrete detail, metric, or example if you have one.
|
|
42
|
+
- Mention tool categories generically if relevant ("we added a structured onboarding workflow") — not brand names.
|
|
43
|
+
- Do NOT name your product.
|
|
44
|
+
- End with a question if it invites further discussion: "What's your current setup?"
|
|
45
|
+
|
|
46
|
+
**Example:**
|
|
47
|
+
Post: "How do you all handle documentation that's always out of date? We update it, then 2 sprints later it's wrong again."
|
|
48
|
+
|
|
49
|
+
Reply: "We treat docs as a release artifact, not a side task. Every PR that changes behavior has to include a docs update before it merges — it's a required check, not a request. It added maybe 10-15 minutes per PR but cut the 'where is the current behavior documented?' questions nearly to zero. The friction is higher upfront but the maintenance overhead dropped a lot."
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### Mode 3 — "What tool/product solves X?" Post
|
|
54
|
+
|
|
55
|
+
The person is explicitly asking for tool recommendations. This is the only mode where you can name the product.
|
|
56
|
+
|
|
57
|
+
**Signals:** Questions like "What tool does X?", "Is there software for Y?", "Looking for a recommendation for Z", "What do you use for X?"
|
|
58
|
+
|
|
59
|
+
**Reply approach:**
|
|
60
|
+
- Name the product and what it does for this specific use case.
|
|
61
|
+
- Be specific about WHY it fits their situation — not a generic feature list.
|
|
62
|
+
- Name at least one alternative so the reply feels balanced and credible.
|
|
63
|
+
- Keep it short. Do not write a product pitch.
|
|
64
|
+
- Do NOT use marketing language. Describe it like you'd tell a friend.
|
|
65
|
+
|
|
66
|
+
**Example:**
|
|
67
|
+
Post: "Looking for a tool to track sales rep performance and ramp time. We're about 20 reps now and spreadsheets aren't cutting it."
|
|
68
|
+
|
|
69
|
+
Reply: "We use Ramp for this — specifically for tracking time-to-first-deal per cohort and seeing where reps get stuck in the process. At 20 reps it starts paying off because you can see whether onboarding gaps are the issue or if it's territory/ICP fit. Alternatives worth looking at are Gong for call analysis and Clari if you want more of a forecasting layer. Depends on whether your bottleneck is rep behavior or pipeline visibility."
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Hard Rules (All Modes)
|
|
74
|
+
|
|
75
|
+
These apply regardless of mode:
|
|
76
|
+
|
|
77
|
+
**Never name the product in Mode 1 or Mode 2.** Not even a subtle reference. If the reply would only make sense if the reader knows your product, rewrite it.
|
|
78
|
+
|
|
79
|
+
**Never the first commenter on a post under 1 hour old.** Early replies to fresh posts look automated.
|
|
80
|
+
|
|
81
|
+
**No links in Mode 1 or Mode 2.** Links in non-recommendation replies look like spam.
|
|
82
|
+
|
|
83
|
+
**Maximum 5 replies drafted per session.** Posting too many replies from the same ICP context signals a bot, not a practitioner.
|
|
84
|
+
|
|
85
|
+
**No banned words in any mode:**
|
|
86
|
+
game-changer, best-in-class, streamline, transform, revolutionize, leverage, seamless, robust, comprehensive, innovative, cutting-edge, world-class, disruptive, groundbreaking, paradigm
|
|
87
|
+
|
|
88
|
+
**No engagement bait:**
|
|
89
|
+
- "What do you think?"
|
|
90
|
+
- "Drop a comment below"
|
|
91
|
+
- "Let me know your thoughts"
|
|
92
|
+
- "Curious what others are experiencing"
|
|
93
|
+
|
|
94
|
+
**Sound human, not polished.** Contractions are fine. Incomplete sentences are fine. Perfect grammar is suspicious on Reddit.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Identifying the Mode
|
|
99
|
+
|
|
100
|
+
If the mode is not obvious from the post title, read the first paragraph of the body. The opening sentence usually signals intent:
|
|
101
|
+
|
|
102
|
+
- "I can't believe how broken..." — Mode 1
|
|
103
|
+
- "Ugh, why is it so hard to..." — Mode 1
|
|
104
|
+
- "How does your team handle..." — Mode 2
|
|
105
|
+
- "What's your process for..." — Mode 2
|
|
106
|
+
- "Looking for a tool that..." — Mode 3
|
|
107
|
+
- "Any recommendations for..." — Mode 3
|
|
108
|
+
- "What do you use for..." — Mode 3
|
|
109
|
+
|
|
110
|
+
When in doubt between Mode 1 and Mode 2, treat it as Mode 1 (no pitching, just empathy and insight).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# reddit-post-engine — Environment Variables
|
|
2
|
+
# ============================================
|
|
3
|
+
# Gemini is required. Composio is optional for direct posting.
|
|
4
|
+
|
|
5
|
+
# Required: Google Gemini API key for post drafting
|
|
6
|
+
# Get it: aistudio.google.com, Get API key
|
|
7
|
+
GEMINI_API_KEY=your_gemini_api_key_here
|
|
8
|
+
|
|
9
|
+
# Optional: Composio API key for direct posting to Reddit
|
|
10
|
+
# Without this: the skill drafts posts for manual submission
|
|
11
|
+
# Get it: app.composio.dev/settings
|
|
12
|
+
# Setup: claude mcp add --transport http reddit-composio "https://mcp.composio.dev/reddit/YOUR_KEY"
|
|
13
|
+
COMPOSIO_API_KEY=your_composio_api_key_here
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# reddit-post-engine
|
|
2
|
+
|
|
3
|
+
<img width="1280" height="640" alt="reddit-post-engine" src="https://github.com/user-attachments/assets/2706f326-5fb9-46fc-851a-ec54ccf53f74" />
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Write and optionally post Reddit content that fits the target subreddit's culture. Fetches subreddit rules and top posts before drafting. Follows the 90/10 rule. Optionally posts via Composio Reddit MCP.
|
|
7
|
+
|
|
8
|
+
## What It Does
|
|
9
|
+
|
|
10
|
+
- Fetches the target subreddit's rules and top posts from Reddit's public API
|
|
11
|
+
- Identifies the subreddit's tone and posting conventions
|
|
12
|
+
- Drafts a title and body that match the community's style
|
|
13
|
+
- Keeps product links out of the body (puts them in the first comment)
|
|
14
|
+
- Optionally posts directly via Composio
|
|
15
|
+
- Covers 7 common subreddits with specific playbooks
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
| Requirement | Purpose | How to Set Up |
|
|
20
|
+
|------------|---------|--------------|
|
|
21
|
+
| Gemini API key | Post drafting and tone matching | aistudio.google.com, Get API key |
|
|
22
|
+
| Composio Reddit MCP (optional) | Direct posting | app.composio.dev |
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
### 1. Configure environment variables
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cp .env.example .env
|
|
30
|
+
# Add GEMINI_API_KEY (required)
|
|
31
|
+
# Add COMPOSIO_API_KEY if you want direct posting
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Connect Reddit via Composio (optional)
|
|
35
|
+
|
|
36
|
+
Direct posting requires a Composio account connected to Reddit OAuth:
|
|
37
|
+
|
|
38
|
+
1. Get your Composio API key at app.composio.dev/settings
|
|
39
|
+
2. Connect Reddit at app.composio.dev/app/reddit
|
|
40
|
+
3. Add the MCP server to Claude Code:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
claude mcp add --transport http reddit-composio \
|
|
44
|
+
"https://mcp.composio.dev/reddit/YOUR_COMPOSIO_API_KEY"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
4. Verify: `claude mcp list` should show `reddit-composio`
|
|
48
|
+
|
|
49
|
+
Without Composio, the skill drafts posts for manual copy-paste submission.
|
|
50
|
+
|
|
51
|
+
## How to Use
|
|
52
|
+
|
|
53
|
+
Draft a post for a specific subreddit:
|
|
54
|
+
```
|
|
55
|
+
"Help me post my project on r/SideProject"
|
|
56
|
+
"Write a Reddit post for r/devops about my Kubernetes tool"
|
|
57
|
+
"Draft something for r/startups: we hit $1k MRR"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
With direct posting:
|
|
61
|
+
```
|
|
62
|
+
"Post my project to r/SideProject via Composio"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Multi-subreddit drafts:
|
|
66
|
+
```
|
|
67
|
+
"Draft posts for r/SideProject and r/indiehackers for my launch"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Subreddit Playbook Summary
|
|
71
|
+
|
|
72
|
+
| Subreddit | Tone | What Works |
|
|
73
|
+
|-----------|------|------------|
|
|
74
|
+
| r/devops | Technical, direct | Problem + solution + specific numbers |
|
|
75
|
+
| r/SideProject | Personal, builder | Build story + honest state + link in comment |
|
|
76
|
+
| r/startups | Business-focused | Lessons learned + metrics |
|
|
77
|
+
| r/programming | Technical, skeptical | Novel approach + code examples |
|
|
78
|
+
| r/ExperiencedDevs | Senior-level | Nuanced tradeoffs, no hand-holding |
|
|
79
|
+
| r/indiehackers | Transparent | Revenue numbers, real story |
|
|
80
|
+
| r/webdev | Friendly | What you built + how it works |
|
|
81
|
+
|
|
82
|
+
## The 90/10 Rule
|
|
83
|
+
|
|
84
|
+
Reddit detects promotional patterns. For your posts to land well, 90% of your Reddit activity should be genuine community contribution: answering questions, discussing topics, sharing interesting links. At most 10% should be posts about your own work.
|
|
85
|
+
|
|
86
|
+
This skill drafts high-quality posts, but the underlying account reputation matters. New accounts with no history posting self-promotional content often get filtered.
|
|
87
|
+
|
|
88
|
+
## Project Structure
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
reddit-post-engine/
|
|
92
|
+
├── SKILL.md
|
|
93
|
+
├── README.md
|
|
94
|
+
├── .env.example
|
|
95
|
+
├── evals/
|
|
96
|
+
│ └── evals.json
|
|
97
|
+
└── references/
|
|
98
|
+
└── subreddit-playbook.md
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT
|