Moniteur Reddit ICP
Surveillez les subreddits à la recherche de personnes décrivant le problème que vous résolvez. Évaluez leur pertinence. Rédigez une réponse utile pour chaque correspondance.
Règle critique : N'inventez jamais d'URLs, de titres ou de contenu de publication. Chaque publication dans la sortie doit provenir d'un résultat de recherche Reddit. Marquez toute section sans résultat par « Aucune correspondance trouvée. » Ne rédigez jamais de réponse à une publication qui n'a pas été retournée par la recherche.
Règle anti-spam : Les réponses rédigées ne doivent jamais mentionner votre produit ou le nom de votre entreprise, sauf si la publication demande explicitement des recommandations d'outils. Sonnez comme un praticien, pas comme un marketeur.
Étape 1 : Vérification de configuration
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+défini}"
echo "REDDIT_CLIENT_ID: ${REDDIT_CLIENT_ID:-non défini, utilisation des endpoints publics (10 requêtes/min)}"
Si GEMINI_API_KEY est manquant : Arrêtez. Dites à l'utilisateur : « GEMINI_API_KEY est requis. Obtenez-le sur aistudio.google.com. Ajoutez-le à votre fichier .env. »
Si les identifiants Reddit sont manquants : Continuez. Utilisez les endpoints JSON publics de Reddit (aucune authentification requise, limite de 10 requêtes/min). Pour la plupart des sessions de surveillance de 3 à 6 recherches de subreddits, cela est suffisant.
Si REDDIT_CLIENT_ID est défini : Utilisez OAuth pour 60 requêtes/min. Récupérez d'abord un jeton :
TOKEN=$(curl -s -X POST \
-d "grant_type=password&username=$REDDIT_USERNAME&password=$REDDIT_PASSWORD" \
--user "$REDDIT_CLIENT_ID:$REDDIT_CLIENT_SECRET" \
-H "User-Agent: varnan-skills/1.0" \
https://www.reddit.com/api/v1/access_token \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
Utilisez Authorization: Bearer $TOKEN et l'URL de base https://oauth.reddit.com pour toutes les requêtes suivantes.
Étape 2 : Chargement de l'ICP
Vérifiez l'existence d'un fichier ICP :
ls docs/icp.md 2>/dev/null && echo "icp trouvé" || echo "icp manquant"
Si docs/icp.md existe : Lisez-le. Extrayez :
product: description du produit en une phrasepain_points: liste d'expressions de points de douleur (langage exact de l'acheteur)anti_keywords: mots-clés qui disqualifient une publicationsubreddits: liste des subreddits à surveiller
Si docs/icp.md n'existe pas : Posez ces 3 questions. Ne continuez pas tant que les 3 n'ont pas été répondues :
- Que fait votre produit ? (une phrase)
- Dans quels subreddits votre ICP publie-t-il ? (séparés par des virgules, ex. devops, startups, SaaS)
- Quelles expressions de points de douleur devraient déclencher une correspondance ? (3 à 5 expressions dans les mots de votre acheteur, ex. « l'onboarding prend une éternité », « je ne vois pas pourquoi les utilisateurs se désabonnent »)
Après avoir recueilli les réponses, sauvegardez dans docs/icp.md au format canonique de references/icp-format.md. Confirmez : « ICP sauvegardé dans docs/icp.md. Il sera utilisé automatiquement lors des prochains lancements. »
Lisez references/icp-format.md pour le format canonique et des exemples de bonnes et mauvaises expressions de points de douleur.
Étape 3 : Recherche sur Reddit
Pour chaque combinaison de subreddit et d'expression de point de douleur, lancez une recherche. Utilisez les endpoints publics sauf si les identifiants OAuth sont définis.
Sans OAuth (endpoint public) :
curl -s \
-H "User-Agent: varnan-skills/1.0" \
"https://www.reddit.com/r/{SUBREDDIT}/search.json?q={PHRASE}&sort=new&t=week&limit=25&restrict_sr=true" \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
posts = d.get('data', {}).get('children', [])
for p in posts:
data = p['data']
print(json.dumps({
'id': data['id'],
'title': data['title'],
'body': data.get('selftext', '')[:600],
'url': 'https://reddit.com' + data['permalink'],
'score': data['score'],
'comments': data['num_comments'],
'subreddit': data['subreddit'],
'created_utc': data['created_utc']
}))
"
Avec OAuth :
Remplacez https://www.reddit.com par https://oauth.reddit.com et ajoutez -H "Authorization: Bearer $TOKEN".
Encodez l'expression dans l'URL avant de l'insérer dans la chaîne de requête :
ENCODED=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" "{PHRASE}")
Fenêtre de temps par défaut :
- Par défaut :
t=week(7 derniers jours) - L'utilisateur dit « aujourd'hui » ou « dernières 24 heures » :
t=day - L'utilisateur dit « ce mois-ci » :
t=month
Après toutes les recherches :
- Rassemblez toutes les publications en une seule liste
- Dédupliquez par ID de publication. Si la même publication correspond à plusieurs expressions, gardez-la une fois et notez toutes les expressions correspondantes.
- Si une recherche retourne 0 publication : notez-le et continuez. Ne vous arrêtez pas.
Indiquez le nombre total de candidats avant l'évaluation : « X publications candidates trouvées dans Y subreddits. »
Étape 4 : Évaluation de pertinence avec Gemini
Écrivez toutes les publications candidates et le contexte ICP dans un fichier temporaire, puis évaluez :
cat > /tmp/reddit-score-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"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."
}]
},
"contents": [{
"parts": [{
"text": "POSTS_AND_ICP_CONTEXT_HERE"
}]
}],
"generationConfig": {
"temperature": 0.2,
"maxOutputTokens": 2048
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/reddit-score-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
Remplacez POSTS_AND_ICP_CONTEXT_HERE par :
- La description du produit et les expressions de points de douleur de l'Étape 2
- Chaque publication candidate : ID, titre, extrait du corps
- Les anti-keywords de l'ICP (Gemini doit attribuer un score plus bas à celles-ci)
Ne conservez que les publications avec un score >= 4 pour la rédaction de réponses.
Indiquez : « X publications ont obtenu un score de 4 ou 5. Rédaction des réponses. »
Si 0 publication a un score >= 4 : affichez le message de résultats nuls de l'Étape 7 et arrêtez. Ne rédigez pas de réponses vides.
Étape 5 : Rédaction des réponses avec Gemini
Lisez references/reply-rules.md avant de rédiger. Déterminez le type de publication pour chaque publication à fort score (Mode 1, 2 ou 3) et transmettez le mode à Gemini.
Pour chaque publication avec un score >= 4, rédigez une réponse (maximum 5 réponses par session) :
cat > /tmp/reddit-reply-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"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."
}]
},
"contents": [{
"parts": [{
"text": "POST_CONTENT_AND_MODE_HERE"
}]
}],
"generationConfig": {
"temperature": 0.7,
"maxOutputTokens": 512
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/reddit-reply-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
Remplacez POST_CONTENT_AND_MODE_HERE par :
- Le titre complet et le corps de la publication
- Le mode de réponse (Mode 1 : frustration/ventilation, Mode 2 : comment gérez-vous X, Mode 3 : recommandation d'outil)
- La description du produit (pour que Gemini sache quoi éviter de nommer en Mode 1/2)
- Si Mode 3 : Gemini peut nommer le produit ET doit nommer une alternative
Étape 6 : Auto-Qualité
Exécutez chaque vérification et corrigez les violations avant de présenter :
- Aucun nom de produit dans les réponses Mode 1 ou Mode 2
- Aucun mot interdit dans les réponses : « game-changer », « best-in-class », « streamline », « transform », « revolutionize », « leverage », « seamless », « robust », « innovative »
- Chaque réponse fait 2 à 5 phrases (comptez et indiquez)
- Chaque réponse répond directement à la question ou frustration spécifique dans la publication
- Toutes les URL dans la sortie sont de vraies URL Reddit provenant des résultats de recherche (pas construites ou devinées)
- Pas plus de 5 réponses rédigées au total
- Les réponses Mode 3 mentionnent au moins une alternative (pas seulement le produit)
- Si un subreddit a retourné 0 résultat pour toutes les recherches de mots-clés, signalez-le dans la sortie
Corrigez toute violation avant de présenter.
Étape 7 : Sortie et sauvegarde
Présentez le rapport complet :
## Reddit ICP Monitor — [AAAA-MM-JJ]
**Subreddits surveillés :** r/[subreddit1], r/[subreddit2]
**Fenêtre de temps :** 7 derniers jours
**Mots-clés recherchés :** [phrase1], [phrase2], [phrase3]
**Candidats trouvés :** X publications
**Correspondances à fort signal (score 4-5) :** Y publications
---
### Correspondance 1 — Score [N]/5
**Publication :** [titre](url)
**Subreddit :** r/[subreddit] | [N] votes positifs | [N] commentaires
**Citation signal :** « [extrait pertinent du corps de la publication] »
**Mot-clé correspondant :** [phrase]
**Type de publication :** Mode [1/2/3]
**Réponse rédigée :**
[texte de la réponse]
**Nombre de mots de la réponse :** N mots
---
[répéter pour chaque correspondance]
---
**Subreddits sans résultat :** [liste de ceux qui n'ont rien retourné]
Si 0 publication a un score >= 4 : « Aucune correspondance à fort signal trouvée au cours des 7 derniers jours sur [subreddits]. Mots-clés recherchés : [liste]. Essayez d'élargir la fenêtre temporelle (relancez en disant 'le mois dernier') ou d'élargir vos expressions de points de douleur dans docs/icp.md. »
Sauvegardez dans un fichier :
mkdir -p docs/reddit-intel
OUTFILE="docs/reddit-intel/$(date +%Y-%m-%d).md"
cat > "$OUTFILE" << 'EOF'
REPORT_CONTENT_HERE
EOF
echo "Sauvegardé dans $OUTFILE"