diff --git a/hands/linkedin/HAND.toml b/hands/linkedin/HAND.toml index a9e8b9d..f4e6093 100644 --- a/hands/linkedin/HAND.toml +++ b/hands/linkedin/HAND.toml @@ -186,6 +186,63 @@ label = "Spanish" value = "auto" label = "Auto-detect from network" +[[settings]] +key = "connection_request_limit" +label = "Connection Request Limit" +description = "Maximum connection requests to send per week (LinkedIn may restrict accounts exceeding 100/week)" +setting_type = "select" +default = "20" + +[[settings.options]] +value = "10" +label = "10 per week (conservative)" + +[[settings.options]] +value = "20" +label = "20 per week (recommended)" + +[[settings.options]] +value = "50" +label = "50 per week (active)" + +[[settings]] +key = "content_media_mode" +label = "Content Media Mode" +description = "Whether posts can include images or document carousels, or stay text-only" +setting_type = "select" +default = "text_only" + +[[settings.options]] +value = "text_only" +label = "Text Only" + +[[settings.options]] +value = "mixed" +label = "Mixed (text + occasional images/carousels)" + +[[settings.options]] +value = "media_rich" +label = "Media Rich (images/carousels preferred)" + +[[settings]] +key = "engagement_reply_depth" +label = "Engagement Reply Depth" +description = "How deeply to engage in comment threads on your own posts" +setting_type = "select" +default = "moderate" + +[[settings.options]] +value = "minimal" +label = "Minimal (reply to direct comments only)" + +[[settings.options]] +value = "moderate" +label = "Moderate (reply to comments + follow-up once)" + +[[settings.options]] +value = "deep" +label = "Deep (sustain multi-turn conversations)" + # ─── Agent configuration ───────────────────────────────────────────────────── [agent] @@ -216,6 +273,12 @@ curl -s -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ If this fails, alert the user that the LINKEDIN_ACCESS_TOKEN is invalid or expired. Extract your LinkedIn member URN from the response. +**Important LinkedIn API limitations to be aware of**: +- LinkedIn does NOT provide a feed-reading API for personal accounts. To "check your feed," use web_search or web_fetch on linkedin.com as a best-effort alternative. Feed-based engagement features may be limited. +- OAuth tokens expire (typically 60 days for access tokens). Always handle 401 errors gracefully. +- The analytics/statistics endpoints require Organization-level access. Personal accounts can only track post-level metrics by re-fetching their own posts. +- There is no API endpoint for reading connection requests or DMs. These features are web-only. + Recover state: 1. memory_recall `linkedin_hand_state` — load previous posting history and performance data 2. Read **User Configuration** for content_style, post_frequency, content_topics, etc. @@ -284,8 +347,58 @@ Only queue A and B grade content. Rewrite C-grade or discard entirely. ## Phase 3 — Posting & Queue Management +### Queue file schema (`linkedin_queue.json`) +```json +{ + "version": 1, + "updated_at": "2025-03-15T10:30:00Z", + "posts": [ + { + "id": "q-20250315-001", + "created_at": "2025-03-15T10:30:00Z", + "scheduled_for": "2025-03-17T08:30:00Z", + "status": "pending_review", + "grade": "A", + "moderation": "SAFE", + "pillar": "industry_insights", + "format": "story", + "content": { + "commentary": "Full post text here...", + "media_type": "none", + "media_path": null, + "first_comment": "Link or extra context for first comment" + }, + "hashtags": ["#Leadership", "#Engineering"], + "review_note": "Strong hook, timely topic" + } + ] +} +``` +Status values: `pending_review`, `approved`, `rejected`, `posted`, `failed`. + +### Posting history schema (`linkedin_posted.json`) +```json +{ + "version": 1, + "posts": [ + { + "queue_id": "q-20250315-001", + "linkedin_post_urn": "urn:li:share:7654321", + "posted_at": "2025-03-17T08:30:00Z", + "metrics_snapshot": { + "impressions": 0, + "reactions": 0, + "comments": 0, + "reposts": 0, + "last_checked": "2025-03-17T08:30:00Z" + } + } + ] +} +``` + If `approval_mode` is ENABLED: -1. Write generated posts to `linkedin_queue.json` +1. Write generated posts to `linkedin_queue.json` using the schema above 2. Write a human-readable `linkedin_queue_preview.md` for review 3. event_publish "linkedin_queue_updated" with queue size 4. Do NOT post — wait for user approval @@ -301,6 +414,20 @@ If `approval_mode` is DISABLED: Note: LinkedIn is migrating from ugcPosts to the newer Posts API. Use /rest/posts endpoint. The author urn format: urn:li:person:{your-linkedin-id} 2. Log each posted content to `linkedin_posted.json` +### Media post handling (when `content_media_mode` is not `text_only`) +- **Images**: Use the 3-step images API flow (register upload -> PUT binary -> create post with image URN). Store the local image path in `media_path` in the queue entry. If image upload fails, fall back to posting as text-only with a note in `review_note`. +- **Document carousels**: Use the documents API flow. Generate carousel slides as a PDF. If PDF generation or upload fails, extract key points and post as a numbered-list text post instead. +- Always keep the text version as fallback — never silently skip a post because media upload failed. + +### API failure fallback strategy +When a LinkedIn API call fails during posting: +1. **HTTP 401 (token expired)**: Alert the user immediately via event_publish "linkedin_token_expired". Queue all remaining posts. Do NOT retry — token refresh requires user action. +2. **HTTP 403 (scope missing)**: Log which scope is missing (e.g., w_member_social). Alert user. Queue post for retry after scope is granted. +3. **HTTP 429 (rate limited)**: Read `X-RateLimit-Reset` header. Reschedule the post for after the reset window. Log the delay in the queue entry. +4. **HTTP 5xx (server error)**: Retry up to 3 times with exponential backoff (2s, 4s, 8s). If all retries fail, move post status to `failed` and schedule retry for next session. +5. **Network error / timeout**: Same as 5xx handling. +6. After any failure, always persist queue state to `linkedin_queue.json` before exiting, so no content is lost. + --- ## Phase 4 — Engagement @@ -311,6 +438,22 @@ If `auto_engage` is enabled: 3. Like posts from people in your professional network 4. NEVER leave generic comments — always add genuine insight +Reply depth follows the `engagement_reply_depth` setting: +- **minimal**: Reply only to direct top-level comments on your posts +- **moderate**: Reply to top-level comments and one follow-up per thread +- **deep**: Sustain multi-turn conversations; ask follow-up questions to keep threads alive (this boosts dwell time signals) + +### Connection request personalization +When sending connection requests (up to `connection_request_limit` per week): +1. **Research first**: Read the person's headline, recent posts, and shared connections before writing the note +2. **Personalize the note** (under 300 characters). Templates by context: + - Shared content interest: "Hi [Name], your post on [topic] resonated — especially [specific point]. Would love to connect and exchange ideas." + - Mutual connection: "Hi [Name], [Mutual] and I worked on [context]. They mentioned your work on [topic] — would be great to connect." + - Event/group: "Hi [Name], enjoyed your comment in [Group/Event] about [topic]. Let's connect!" +3. **Never pitch** in the connection request. Save business conversations for after the connection is accepted. +4. **Track acceptance rate** in memory. If acceptance rate drops below 40%, reduce volume and improve note quality. +5. **Respect the weekly limit** strictly — LinkedIn may restrict accounts that send excessive requests. + --- ## Phase 5 — Performance Tracking @@ -404,6 +547,7 @@ default_active = false [i18n.zh] name = "LinkedIn Hand" description = "自主 LinkedIn 管理——个人资料优化、内容创作、人脉拓展和职业互动" +<<<<<<< HEAD category = "通信" [i18n.zh.settings.content_style] @@ -632,3 +776,306 @@ description = "콘텐츠의 주요 대상 독자" [i18n.ko.settings.language] label = "언어" description = "게시물 및 소통에 사용하는 언어" +||||||| parent of e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) +======= +category = "通信" + +[i18n.zh.settings.content_style] +label = "内容风格" +description = "LinkedIn 帖子的语气和风格" + +[i18n.zh.settings.post_frequency] +label = "发布频率" +description = "创建和发布内容的频率" + +[i18n.zh.settings.content_topics] +label = "内容主题" +description = "要创作内容的主题(逗号分隔,例如 AI、领导力、创业)" + +[i18n.zh.settings.auto_engage] +label = "自动互动" +description = "自动对人脉网络中的相关帖子点赞和评论" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将帖子加入队列等待审核,而非直接发布" + +[i18n.zh.settings.hashtag_count] +label = "话题标签数量" +description = "每篇帖子包含的话题标签数量" + +[i18n.zh.settings.target_audience] +label = "目标受众" +description = "内容的主要目标受众" + +[i18n.zh.settings.language] +label = "语言" +description = "帖子和互动使用的语言" + +[i18n.zh.settings.connection_request_limit] +label = "连接请求上限" +description = "每周发送连接请求的最大数量(超过 100/周可能导致账号被限制)" + +[i18n.zh.settings.content_media_mode] +label = "内容媒体模式" +description = "帖子是否包含图片或文档轮播,还是仅使用纯文本" + +[i18n.zh.settings.engagement_reply_depth] +label = "互动回复深度" +description = "在自己帖子的评论区中参与讨论的深度" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "LinkedIn Hand" +description = "自律型LinkedInマネージャー——プロフィール最適化、コンテンツ作成、ネットワーキング、プロフェッショナルエンゲージメント" +category = "コミュニケーション" + +[i18n.ja.settings.content_style] +label = "コンテンツスタイル" +description = "LinkedIn投稿の語調とスタイル" + +[i18n.ja.settings.post_frequency] +label = "投稿頻度" +description = "コンテンツの作成・投稿の頻度" + +[i18n.ja.settings.content_topics] +label = "コンテンツトピック" +description = "作成するコンテンツのトピック(カンマ区切り、例: AI、リーダーシップ、スタートアップ)" + +[i18n.ja.settings.auto_engage] +label = "自動エンゲージメント" +description = "ネットワーク内の関連投稿に自動でいいねやコメントをする" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "投稿を直接公開せず、レビュー用キューに追加する" + +[i18n.ja.settings.hashtag_count] +label = "ハッシュタグ数" +description = "各投稿に含めるハッシュタグの数" + +[i18n.ja.settings.target_audience] +label = "ターゲットオーディエンス" +description = "コンテンツの主なターゲット層" + +[i18n.ja.settings.language] +label = "言語" +description = "投稿とエンゲージメントに使用する言語" + +[i18n.ja.settings.connection_request_limit] +label = "つながり申請上限" +description = "週あたりのつながり申請送信上限数(100件/週を超えるとアカウントが制限される可能性があります)" + +[i18n.ja.settings.content_media_mode] +label = "コンテンツメディアモード" +description = "投稿に画像やドキュメントカルーセルを含めるか、テキストのみにするか" + +[i18n.ja.settings.engagement_reply_depth] +label = "エンゲージメント返信深度" +description = "自分の投稿のコメントスレッドにどの程度深く参加するか" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de LinkedIn" +description = "Gestor autónomo de LinkedIn — optimización de perfil, creación de contenido, networking y engagement profesional" +category = "Comunicación" + +[i18n.es.settings.content_style] +label = "Estilo de contenido" +description = "Voz y tono para las publicaciones de LinkedIn" + +[i18n.es.settings.post_frequency] +label = "Frecuencia de publicación" +description = "Con qué frecuencia crear y publicar contenido" + +[i18n.es.settings.content_topics] +label = "Temas de contenido" +description = "Temas sobre los que crear contenido (separados por comas, ej. IA, liderazgo, startups)" + +[i18n.es.settings.auto_engage] +label = "Engagement automático" +description = "Dar like y comentar automáticamente en publicaciones relevantes de tu red" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Poner publicaciones en cola para revisión en lugar de publicarlas directamente" + +[i18n.es.settings.hashtag_count] +label = "Cantidad de hashtags" +description = "Número de hashtags a incluir por publicación" + +[i18n.es.settings.target_audience] +label = "Audiencia objetivo" +description = "Audiencia principal para tu contenido" + +[i18n.es.settings.language] +label = "Idioma" +description = "Idioma para publicaciones e interacciones" + +[i18n.es.settings.connection_request_limit] +label = "Limite de solicitudes de conexion" +description = "Numero maximo de solicitudes de conexion por semana (superar 100/semana puede restringir la cuenta)" + +[i18n.es.settings.content_media_mode] +label = "Modo de contenido multimedia" +description = "Si las publicaciones incluyen imagenes o carruseles de documentos, o solo texto" + +[i18n.es.settings.engagement_reply_depth] +label = "Profundidad de respuesta" +description = "Nivel de participacion en los hilos de comentarios de tus publicaciones" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand LinkedIn" +description = "Gestionnaire LinkedIn autonome — optimisation de profil, création de contenu, réseautage et engagement professionnel" +category = "Communication" + +[i18n.fr.settings.content_style] +label = "Style de contenu" +description = "Ton et style pour les publications LinkedIn" + +[i18n.fr.settings.post_frequency] +label = "Fréquence de publication" +description = "Fréquence de création et de publication de contenu" + +[i18n.fr.settings.content_topics] +label = "Sujets de contenu" +description = "Sujets sur lesquels créer du contenu (séparés par des virgules, ex. IA, leadership, startups)" + +[i18n.fr.settings.auto_engage] +label = "Engagement automatique" +description = "Aimer et commenter automatiquement les publications pertinentes de votre réseau" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Mettre les publications en file d'attente pour révision au lieu de les publier directement" + +[i18n.fr.settings.hashtag_count] +label = "Nombre de hashtags" +description = "Nombre de hashtags à inclure par publication" + +[i18n.fr.settings.target_audience] +label = "Public cible" +description = "Public principal pour votre contenu" + +[i18n.fr.settings.language] +label = "Langue" +description = "Langue pour les publications et les interactions" + +[i18n.fr.settings.connection_request_limit] +label = "Limite de demandes de connexion" +description = "Nombre maximum de demandes de connexion par semaine (depasser 100/semaine peut entrainer des restrictions)" + +[i18n.fr.settings.content_media_mode] +label = "Mode media du contenu" +description = "Inclure des images ou carrousels dans les publications, ou rester en texte uniquement" + +[i18n.fr.settings.engagement_reply_depth] +label = "Profondeur de reponse" +description = "Niveau d'implication dans les fils de commentaires de vos publications" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "LinkedIn-Hand" +description = "Autonomer LinkedIn-Manager — Profiloptimierung, Content-Erstellung, Networking und professionelles Engagement" +category = "Kommunikation" + +[i18n.de.settings.content_style] +label = "Inhaltsstil" +description = "Ton und Stil für LinkedIn-Beiträge" + +[i18n.de.settings.post_frequency] +label = "Veröffentlichungshäufigkeit" +description = "Wie oft Inhalte erstellt und veröffentlicht werden" + +[i18n.de.settings.content_topics] +label = "Inhaltsthemen" +description = "Themen für die Content-Erstellung (kommagetrennt, z.B. KI, Führung, Startups)" + +[i18n.de.settings.auto_engage] +label = "Automatisches Engagement" +description = "Relevante Beiträge im Netzwerk automatisch liken und kommentieren" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Beiträge zur Überprüfung in die Warteschlange stellen, anstatt sie direkt zu veröffentlichen" + +[i18n.de.settings.hashtag_count] +label = "Anzahl Hashtags" +description = "Anzahl der Hashtags pro Beitrag" + +[i18n.de.settings.target_audience] +label = "Zielgruppe" +description = "Primäre Zielgruppe für Ihre Inhalte" + +[i18n.de.settings.language] +label = "Sprache" +description = "Sprache für Beiträge und Interaktionen" + +[i18n.de.settings.connection_request_limit] +label = "Kontaktanfragen-Limit" +description = "Maximale Anzahl an Kontaktanfragen pro Woche (über 100/Woche kann zu Einschränkungen führen)" + +[i18n.de.settings.content_media_mode] +label = "Inhalts-Medien-Modus" +description = "Ob Beiträge Bilder oder Dokumentenkarussells enthalten oder nur Text verwenden" + +[i18n.de.settings.engagement_reply_depth] +label = "Antworttiefe" +description = "Wie intensiv in Kommentarthreads der eigenen Beiträge mitdiskutiert wird" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "LinkedIn Hand" +description = "자율 LinkedIn 관리 — 프로필 최적화, 콘텐츠 제작, 네트워킹 및 전문적 소통" +category = "커뮤니케이션" + +[i18n.ko.settings.content_style] +label = "콘텐츠 스타일" +description = "LinkedIn 게시물의 어조와 스타일" + +[i18n.ko.settings.post_frequency] +label = "게시 빈도" +description = "콘텐츠를 작성하고 게시하는 주기" + +[i18n.ko.settings.content_topics] +label = "콘텐츠 주제" +description = "콘텐츠를 작성할 주제 (쉼표로 구분, 예: AI, 리더십, 스타트업)" + +[i18n.ko.settings.auto_engage] +label = "자동 소통" +description = "네트워크 내 관련 게시물에 자동으로 좋아요 및 댓글" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "게시물을 직접 게시하지 않고 대기열에 추가하여 검토" + +[i18n.ko.settings.hashtag_count] +label = "해시태그 수" +description = "게시물당 포함할 해시태그 수" + +[i18n.ko.settings.target_audience] +label = "대상 독자" +description = "콘텐츠의 주요 대상 독자" + +[i18n.ko.settings.language] +label = "언어" +description = "게시물 및 소통에 사용하는 언어" + +[i18n.ko.settings.connection_request_limit] +label = "연결 요청 한도" +description = "주당 최대 연결 요청 수 (100건/주 초과 시 계정이 제한될 수 있음)" + +[i18n.ko.settings.content_media_mode] +label = "콘텐츠 미디어 모드" +description = "게시물에 이미지나 문서 캐러셀을 포함할지, 텍스트만 사용할지 설정" + +[i18n.ko.settings.engagement_reply_depth] +label = "소통 답글 깊이" +description = "자신의 게시물 댓글 스레드에 얼마나 깊이 참여할지 설정" +>>>>>>> e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) diff --git a/hands/linkedin/SKILL.md b/hands/linkedin/SKILL.md index a136372..3569599 100644 --- a/hands/linkedin/SKILL.md +++ b/hands/linkedin/SKILL.md @@ -83,11 +83,29 @@ curl -s -X POST "https://api.linkedin.com/rest/socialActions/URN/likes" \ ### The LinkedIn Algorithm (2024-2025) Key factors that affect reach: -1. **Dwell time**: How long people spend reading your post -2. **Early engagement**: Comments in the first hour boost distribution -3. **Meaningful comments**: Long comments signal quality content -4. **No external links**: Posts with links get 40-50% less reach -5. **Personal stories**: Narrative content outperforms promotional content +1. **Dwell time**: How long people spend reading your post. LinkedIn tracks both "read dwell" (time spent on post text) and "click dwell" (time spent after clicking "see more"). Longer posts that hold attention get amplified. Ideal: 800-1300 characters that reward reading to the end. +2. **Early engagement**: Comments in the first 60-90 minutes are weighted heavily. The algorithm decides distribution tiers within 2 hours of posting. +3. **Meaningful comments**: Long comments (3+ sentences) signal quality far more than likes. One thoughtful comment is worth ~10 likes in the algorithm. Reply-to-reply threads (nested comments) further boost the post. +4. **No external links**: Posts with links get 40-50% less reach. The algorithm deprioritizes anything that drives users off-platform. +5. **Personal stories**: Narrative content outperforms promotional content. The algorithm favors "knowledge and advice" posts from individuals over brand content. + +**Engagement signal weighting** (approximate relative impact on distribution): +| Signal | Relative Weight | Why | +|--------|----------------|-----| +| Comment (3+ sentences) | 10x | Strongest indicator of quality content | +| Repost with commentary | 8x | Shows content worth sharing and adding to | +| Save/bookmark | 6x | High-intent signal — user wants to revisit | +| Reply in comment thread | 5x | Sustained conversation signals value | +| Share (plain repost) | 4x | Distribution signal but lower intent | +| Reaction (any emoji) | 1x | Baseline engagement, lowest weight | +| Click "see more" | 0.5x | Curiosity signal, but no follow-through guarantee | + +**Algorithm penalty signals**: +- Editing a post within 10 minutes of publishing can reset distribution +- Deleting and reposting gets flagged and suppressed +- Posting more than once per 18 hours splits your audience +- Engagement pods (coordinated likes/comments) are detected and penalized +- Hashtag stuffing (>5) triggers spam signals ### Content Pillars @@ -218,6 +236,7 @@ Before posting any content, classify it: - Credit sources and tag collaborators - Disclose affiliations when discussing products or services - Respect intellectual property and copyright +<<<<<<< HEAD --- @@ -968,3 +987,807 @@ DMs are open. Or drop a comment and I'll reach out. #OpenToWork #EngineeringManager #Hiring #Leadership ``` +||||||| parent of e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) +======= + +### Crisis Management for Negative Engagement + +When a post receives significant negative attention (hostile comments, public disagreements, misinterpretation): + +**Severity levels and response**: + +| Level | Indicators | Action | +|-------|-----------|--------| +| **Low** | 1-2 disagreeing comments, professional tone | Respond thoughtfully; treat as healthy discussion | +| **Medium** | Multiple negative comments, some personal attacks, post being quote-shared critically | Pause auto-engagement; draft a measured clarification comment; queue for user review | +| **High** | Viral negative attention, accusations of misinformation, brand/employer reputation risk | Alert user immediately via event_publish "linkedin_crisis_alert"; do NOT auto-respond; prepare a response draft for human approval | + +**Response playbook**: +1. **Never delete a post** that has active engagement -- it signals guilt and people screenshot first +2. **Never argue in comment threads** -- one measured response per critic, then disengage +3. **Acknowledge valid criticism** gracefully: "That's a fair point -- I should have been clearer about [X]. Here's what I meant: ..." +4. **For factual errors** in your post: Add a correction comment pinned at the top: "Update: [correction]. Thanks to @Name for pointing this out." +5. **For personal attacks**: Do not respond. Hide the comment (LinkedIn allows this) and move on. If persistent, report to LinkedIn. +6. **For misinterpretation at scale**: Write a follow-up post (not an edit) that clarifies the original point without being defensive + +**After a crisis**: Log the incident in memory, note what triggered it, and update content moderation rules to prevent recurrence. + +--- + +## Advanced API Patterns + +### Image Post Creation (Media Upload Flow) + +Posting an image requires a 3-step flow: register upload, upload binary, then create post. + +**Step 1 -- Register the upload**: +```bash +curl -s -X POST "https://api.linkedin.com/rest/images?action=initializeUpload" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "initializeUploadRequest": { + "owner": "urn:li:person:MEMBER_ID" + } + }' +``` +Response contains `uploadUrl` and `image` URN (e.g., `urn:li:image:C4E...`). + +**Step 2 -- Upload the binary**: +```bash +curl -s -X PUT "$UPLOAD_URL" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: image/png" \ + --data-binary "@/path/to/image.png" +``` + +**Step 3 -- Create post with image**: +```bash +curl -s -X POST "https://api.linkedin.com/rest/posts" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "author": "urn:li:person:MEMBER_ID", + "lifecycleState": "PUBLISHED", + "commentary": "Check out our Q3 results!", + "visibility": "PUBLIC", + "distribution": {"feedDistribution": "MAIN_FEED"}, + "content": { + "media": { + "id": "urn:li:image:IMAGE_URN", + "title": "Q3 Performance Summary" + } + } + }' +``` + +### Document Post Creation (PDF/Carousel) + +LinkedIn "document posts" (carousels) follow the same register-upload-post pattern but use the documents API. + +**Register document upload**: +```bash +curl -s -X POST "https://api.linkedin.com/rest/documents?action=initializeUpload" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "initializeUploadRequest": { + "owner": "urn:li:person:MEMBER_ID" + } + }' +``` + +**Upload the PDF and create post** (same pattern as image -- PUT binary, then POST with `content.media.id` set to the document URN). + +### Article Publishing via API + +**Create an article post** (link article hosted externally): +```bash +curl -s -X POST "https://api.linkedin.com/rest/posts" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "author": "urn:li:person:MEMBER_ID", + "lifecycleState": "PUBLISHED", + "commentary": "I wrote about why most engineering teams get incident response wrong.\n\nKey insight: the 5-minute rule changes everything.", + "visibility": "PUBLIC", + "distribution": {"feedDistribution": "MAIN_FEED"}, + "content": { + "article": { + "source": "https://yourblog.com/incident-response", + "title": "The 5-Minute Rule for Incident Response", + "description": "A practical framework for engineering teams" + } + } + }' +``` + +> **Note**: Article-link posts get reduced reach vs native text posts. Prefer putting links in the first comment. + +### Analytics Endpoints + +**Get post statistics (organic)**: +```bash +curl -s -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "LinkedIn-Version: 202405" \ + "https://api.linkedin.com/rest/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:ORG_ID&timeIntervals.timeGranularityType=DAY&timeIntervals.timeRange.start=1704067200000&timeIntervals.timeRange.end=1706745600000" +``` + +**Get share statistics for a specific post**: +```bash +curl -s -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "LinkedIn-Version: 202405" \ + "https://api.linkedin.com/rest/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:ORG_ID&shares=urn:li:share:SHARE_ID" +``` + +Response fields: +| Field | Description | +|-------|-------------| +| `totalShareStatistics.impressionCount` | Total times the post appeared in feeds | +| `totalShareStatistics.uniqueImpressionsCount` | Unique viewers | +| `totalShareStatistics.clickCount` | Total clicks (content + read more) | +| `totalShareStatistics.likeCount` | Total likes/reactions | +| `totalShareStatistics.commentCount` | Total comments | +| `totalShareStatistics.shareCount` | Total reposts | +| `totalShareStatistics.engagement` | Engagement rate (decimal) | + +**Get follower statistics** (organization pages): +```bash +curl -s -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "LinkedIn-Version: 202405" \ + "https://api.linkedin.com/rest/organizationalEntityFollowerStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:ORG_ID" +``` + +### Webhook / Notification Patterns + +LinkedIn does not offer real-time webhooks for most events. Use polling instead: + +``` +Polling strategy: + - Post engagement: Poll every 15 minutes for first 4 hours after posting + - Mentions/comments: Poll every 5 minutes during engagement_hours + - Follower counts: Poll once per day + - Analytics: Poll once per day (data lags 24-48 hours) +``` + +### Error Handling and Rate Limit Retry + +``` +Rate limit response headers: + X-RateLimit-Limit: 100 + X-RateLimit-Remaining: 0 + X-RateLimit-Reset: 1706745600 + +HTTP 429 response: + {"status": 429, "message": "Resource level throttle limit..."} +``` + +**Retry strategy**: +``` +1. On HTTP 429: Read X-RateLimit-Reset header +2. Calculate wait_seconds = reset_timestamp - current_timestamp +3. Sleep for wait_seconds + 1 (buffer) +4. Retry the request (max 3 retries) +5. On 3 consecutive 429s: back off for 15 minutes + +On HTTP 5xx (server error): +1. Retry with exponential backoff: 1s, 2s, 4s +2. Max 3 retries +3. Log failure and queue for later retry + +On HTTP 401 (expired token): +1. Trigger OAuth 2.0 refresh flow +2. Update stored token +3. Retry original request once +``` + +--- + +## Content Calendar Template + +### Monthly Content Planning Framework + +Organize content around weekly themes that rotate through your content pillars. + +``` +MONTH: [Month Year] +THEME ROTATION: + Week 1: [Pillar 1 -- e.g., Engineering Leadership] + Week 2: [Pillar 2 -- e.g., Industry Trends] + Week 3: [Pillar 3 -- e.g., Career Growth] + Week 4: [Pillar 1 deep dive OR seasonal/timely topic] +``` + +### Weekly Content Schedule + +``` +WEEK OF [DATE] — Theme: [Weekly Theme] + +Monday: + - 8:30 AM: [Personal story] tied to weekly theme + Format: Hook + narrative + lesson + question + Goal: High engagement to start the week + +Tuesday: + - 9:00 AM: [Step-by-step guide] or [How-to] + Format: Numbered list with tactical advice + Goal: Saves and shares (authority building) + +Wednesday: + - 8:30 AM: [Data/insight post] with original analysis + Format: Stat + context + your take + question + Goal: Credibility and thought leadership + +Thursday: + - 9:00 AM: [Contrarian take] or [Industry opinion] + Format: Bold statement + reasoning + invitation to debate + Goal: Comments and discussion (algorithm boost) + +Friday: + - 8:00 AM: [Engagement post] — poll, question, or lightweight personal content + Format: Short, conversational, easy to respond to + Goal: Community building before weekend +``` + +### Content Mix Ratios + +| Category | % of Posts | Examples | +|----------|-----------|----------| +| Educational / Value | 40% | How-tos, frameworks, lessons learned | +| Personal / Storytelling | 25% | Career stories, failures, reflections | +| Engagement / Discussion | 20% | Questions, polls, contrarian takes | +| Promotional / Company | 10% | Product launches, hiring, milestones | +| Curated / Commentary | 5% | Industry news with your analysis | + +**Rule**: Never let promotional content exceed 15%. LinkedIn penalizes overtly sales-y accounts. + +### Engagement Windows and Response Strategy + +``` +Post published at 8:30 AM: + Minutes 0-15: Reply to EVERY comment immediately (signals activity to algorithm) + Minutes 15-60: Reply within 5 minutes of each new comment + Hours 1-4: Reply within 30 minutes + Hours 4-24: Reply within 2 hours (during business hours) + Day 2+: Reply within 24 hours + +First-comment strategy: + - Post your own comment within 2 minutes of publishing + - Use it for: link to resource, additional context, question to spark discussion + - This comment acts as engagement seed +``` + +--- + +## Analytics & Optimization + +### Key Metrics to Track + +| Metric | Formula | Good Benchmark | Great Benchmark | +|--------|---------|----------------|-----------------| +| Engagement rate | (reactions + comments + reposts) / impressions | > 2% | > 5% | +| Comment rate | comments / impressions | > 0.3% | > 1% | +| Follower growth rate | net new followers / total followers per week | > 0.5% | > 2% | +| Profile views | weekly profile views trend | Consistent growth | 2x after viral post | +| SSI (Social Selling Index) | LinkedIn's built-in score (0-100) | > 50 | > 70 | +| Content saves | saves / impressions | > 0.5% | > 2% | +| Click-through rate | clicks / impressions | > 1% | > 3% | + +### Engagement Rate Calculation + +``` +engagement_rate = (reactions + comments + reposts) / impressions * 100 + +Example: + 120 reactions + 35 comments + 8 reposts = 163 engagements + 163 / 5,200 impressions = 3.13% engagement rate + +Per-post tracking: + | Post Date | Topic | Format | Impressions | Eng Rate | Comments | + |-----------|-------|--------|-------------|----------|----------| + | Mon 03/03 | Leadership | Story | 5,200 | 3.13% | 35 | + | Tue 03/04 | AI Tools | How-to | 3,800 | 4.21% | 22 | + | Wed 03/05 | Hiring | Data | 2,100 | 2.85% | 12 | +``` + +### A/B Testing Strategies + +Test one variable at a time across pairs of similar posts: + +| Variable | Option A | Option B | Track | +|----------|----------|----------|-------| +| Hook style | Question hook | Bold statement hook | Click-through rate | +| Post length | Short (< 800 chars) | Long (1200+ chars) | Dwell time, engagement | +| Posting time | 8:00 AM | 9:30 AM | Impressions after 4 hours | +| CTA type | Question CTA | "Agree? Repost" CTA | Comment rate vs repost rate | +| Hashtag count | 3 hashtags | 0 hashtags | Reach beyond network | +| Format | Plain text | Text + image | Engagement rate | + +**How to run a test**: +1. Pick one variable to test (e.g., posting time) +2. Keep everything else constant (same pillar, similar format, similar length) +3. Run for 2 weeks (minimum 4 posts per variant) +4. Compare average metrics -- ignore outliers +5. Adopt the winner and move to next variable + +**A/B test tracking template** (store in `linkedin_ab_tests.json`): +```json +{ + "test_id": "test-hook-style-001", + "variable": "hook_style", + "hypothesis": "Bold statement hooks generate higher click-through than question hooks", + "start_date": "2025-03-10", + "end_date": "2025-03-24", + "status": "running", + "variant_a": { + "description": "Question hook", + "post_ids": ["q-20250310-001", "q-20250312-001", "q-20250314-001"], + "avg_impressions": 3200, + "avg_engagement_rate": 2.8, + "avg_comment_rate": 0.4 + }, + "variant_b": { + "description": "Bold statement hook", + "post_ids": ["q-20250311-001", "q-20250313-001", "q-20250315-001"], + "avg_impressions": 4100, + "avg_engagement_rate": 3.5, + "avg_comment_rate": 0.6 + }, + "conclusion": null +} +``` + +**Statistical rigor**: With LinkedIn's natural variance, require at least 4 posts per variant and a >20% difference in the primary metric before declaring a winner. If the difference is <20%, the test is inconclusive -- run for another week or accept that the variable does not materially affect performance. + +### Identifying Top-Performing Content Patterns + +After 30+ posts, analyze your data to find patterns: + +``` +Sort all posts by engagement rate (descending): + 1. Look at your top 5 posts — what do they share? + - Same content pillar? + - Same format (story, how-to, contrarian)? + - Same hook style? + - Similar length range? + - Same posting day/time? + 2. Look at your bottom 5 posts — what went wrong? + - External links in body? + - Promotional tone? + - Published on Friday/weekend? + - Weak hook? + 3. Create your "hit formula": + Best combo: [Pillar] + [Format] + [Hook style] + [Day/Time] + Example: "Engineering Leadership + Personal Story + Confession Hook + Tuesday 8:30 AM" +``` + +--- + +## Audience Growth Strategies + +### Comment-First Strategy + +The fastest way to grow on LinkedIn is strategic commenting on high-visibility posts. + +**How it works**: +1. Identify 15-20 active creators in your niche (10K+ followers) +2. Turn on notifications for their posts +3. Be among the first 5 comments on their new posts +4. Write substantive comments (3-5 sentences) that add genuine value + +**Comment templates for growth**: +``` +Adding a data point: + "This resonates. At [Company/Role], we saw [specific metric] when we + implemented [related approach]. The key difference was [insight]. + Curious if others have seen similar results?" + +Respectful counterpoint: + "Interesting perspective. I'd push back slightly on [point] — in my + experience with [context], the opposite was true because [reason]. + That said, I think [original point] absolutely holds for [use case]." + +Extending the idea: + "Building on this — one thing I'd add is [new angle]. I wrote about + this recently and the biggest takeaway was [specific insight]. + [Question that invites further discussion]?" +``` + +**Target**: 5-10 thoughtful comments per day during peak hours (8-10 AM). + +### Collaborative Content Patterns + +**Tagging strategy**: +- Tag 1-3 people who would genuinely find the content relevant +- Always explain WHY you're tagging them (not drive-by tags) +- Tag people you've already engaged with (they're more likely to respond) + +``` +Example post with strategic tags: + "I've been thinking about how engineering teams handle on-call rotations. + + After talking to 20+ eng managers, here are the 3 models that actually work: + + 1. Follow-the-sun (best for distributed teams) + 2. Volunteer-first rotation (best for small teams) + 3. Tiered escalation (best for complex systems) + + @Name1 — your team's approach to #2 was eye-opening. + @Name2 — curious if your distributed team uses #1 or something else? + + What model does your team use? Reply with your team size." +``` + +**Co-creation patterns**: +- Interview a peer and post key insights (tag them, they reshare) +- "X people I learned from this year" posts (mass tagging, high reshare rate) +- Collaborative lists: "Drop your best [resource] in the comments, I'll compile and share" + +### LinkedIn Newsletter Strategy + +Newsletters convert profile visitors into subscribers with direct inbox delivery. + +**Newsletter setup checklist**: +``` +1. Name: Clear, specific, benefit-driven + Good: "The Engineering Leader's Playbook" + Bad: "My Thoughts on Things" + +2. Cadence: Weekly or biweekly (consistency > frequency) + +3. Format: + - 800-1500 words (longer than posts, shorter than blog articles) + - One core idea per issue + - Actionable takeaways or frameworks + - End with a question to drive comments + +4. Promotion: + - Announce each issue with a teaser post (don't just auto-share) + - Reference newsletter content in regular posts + - Cross-promote with other newsletter authors +``` + +**Newsletter content structure**: +``` +Issue #[N]: [Compelling Title] + +[Hook paragraph -- why this matters NOW] + +[Section 1: The Problem / Context] + - 2-3 paragraphs with specific examples + +[Section 2: The Framework / Solution] + - Numbered steps or clear model + - Real-world application examples + +[Section 3: How to Apply This] + - Actionable next steps the reader can take today + +[Closing: Question + CTA] + "What's your experience with [topic]? Reply in the comments." + "If you found this useful, share it with your team." +``` + +### LinkedIn Live and Events + +**LinkedIn Live** broadcasts get 7x more reactions and 24x more comments than regular video posts. + +**Live session framework**: +``` +Pre-event (1 week before): + - Create LinkedIn Event and post announcement + - Send invites to relevant connections + - Post 2-3 teaser posts building anticipation + +During event: + - Start 2 minutes early for tech check + - Open with clear agenda (30 seconds) + - Acknowledge live commenters by name + - Keep sessions 20-40 minutes + +Post-event: + - Post key takeaways within 2 hours + - Reply to all comments on the event post + - Repurpose recording into 3-5 short clips for future posts +``` + +**Event types that work**: +| Type | Duration | Best For | Frequency | +|------|----------|----------|-----------| +| AMA (Ask Me Anything) | 30 min | Engagement, authority | Monthly | +| Industry deep dive | 20 min | Thought leadership | Biweekly | +| Interview / fireside chat | 40 min | Network growth | Monthly | +| Quick tip / hot take | 10 min | Visibility | Weekly | + +--- + +## Worked Examples + +### Example 1: Thought Leadership Campaign + +**Scenario**: VP of Engineering building authority in "engineering culture" niche. + +**Content pillars**: +``` +Pillar 1: Engineering Management (40%) +Pillar 2: Scaling Teams (30%) +Pillar 3: Career Advice (20%) +Pillar 4: Personal Lessons (10%) +``` + +**Week 1 posting schedule with sample posts**: + +**Monday 8:30 AM -- Personal Story (Pillar 1)**: +``` +I promoted my worst interviewer to Head of Recruiting. + +Sounds crazy. Here's what happened. + +She kept rejecting candidates everyone else loved. +Her "pass rate" was 15%. Team average was 60%. + +But after 12 months, something became clear: + +Her hires had: +→ 94% retention rate (team avg: 71%) +→ 2.3x faster time to first meaningful contribution +→ Zero PIPs in their first year + +She wasn't a bad interviewer. +She was the only one actually doing it right. + +The lesson? +Measure what matters. Pass rates reward speed. +Retention rates reward judgment. + +What's one metric your team optimizes for +that might be the wrong one? + +#EngineeringLeadership #Hiring #TechManagement +``` + +**Tuesday 9:00 AM -- How-To Guide (Pillar 2)**: +``` +How to run a team retrospective that people actually enjoy +(not the soul-crushing ones everyone dreads): + +Step 1: Kill the "what went well / what didn't" format +→ Use "I wish... I wonder... I'm proud of..." instead + +Step 2: Timebox ruthlessly +→ 45 minutes max. If it takes longer, your team is too big for one retro. + +Step 3: One action item per person, max +→ A retro with 20 action items produces zero change. +→ One item per person = accountability. + +Step 4: Start with appreciation +→ First 5 minutes: each person thanks someone else on the team. +→ This changes the entire energy of the room. + +Step 5: Rotate the facilitator +→ The manager should NOT always run retros. +→ It changes what people feel safe saying. + +I've used this format with teams of 5 to teams of 50. + +What's your retro format? Drop it below -- +I'm always looking for new approaches. + +#Agile #EngineeringCulture #TeamManagement +``` + +**Wednesday 8:30 AM -- Data + Insight (Pillar 2)**: +``` +We tracked every engineering team meeting for 6 months. + +The data was uncomfortable. + +→ Average engineer: 11.2 hours/week in meetings +→ Senior engineers: 16.4 hours/week +→ Time spent in meetings that could've been async: 62% + +We cut 40% of recurring meetings. + +Result after 3 months: +→ Sprint velocity: +23% +→ Engineer satisfaction: +31% (internal survey) +→ "Deep work" blocks per week: 2.1 → 4.7 + +The surprising part? +Nobody missed the deleted meetings. +Not one person asked to bring them back. + +If you haven't audited your meeting load recently, +you're probably burning 30-40% of your team's capacity. + +What % of your meetings could be an async update? + +#Engineering #Productivity #Leadership +``` + +**Thursday 9:00 AM -- Contrarian Take (Pillar 3)**: +``` +Unpopular opinion: "Culture fit" interviews should be illegal. + +Here's why: + +Culture fit = "do I want to get a beer with this person?" +That's not hiring. That's friend-making. + +What actually matters: +→ Values alignment (do they care about the same outcomes?) +→ Working style compatibility (async vs sync, docs vs meetings) +→ Growth trajectory (will they push the team forward?) + +None of those require "fitting in." + +The best hire I ever made was someone who challenged +every assumption we had. They didn't "fit" our culture. + +They made it better. + +Replace "culture fit" with "culture add." + +Agree or disagree? I'd love to hear your take. + +#Hiring #Diversity #EngineeringCulture #Leadership +``` + +**Friday 8:00 AM -- Engagement Post (Pillar 4)**: +``` +Fill in the blank: + +"The best career advice I ever received was ___________." + +I'll go first: + +"Stop optimizing for your next promotion. +Start optimizing for your next learning curve." + +Changed how I made every career decision since. + +Your turn. + +#CareerAdvice #ProfessionalGrowth +``` + +### Example 2: Company Page Management + +**Scenario**: B2B SaaS company (Series B, 80 employees) managing their LinkedIn company page. + +**Posting cadence**: +``` +Company page: 4-5 posts per week +Employee advocacy: 2-3 employees reshare/post per week +Executive accounts: CEO + CTO post 2-3x/week each +``` + +**Weekly company page schedule**: +``` +Monday: Industry insight or thought leadership (educational) +Tuesday: Product tip or customer use case (value-driven) +Wednesday: Team/culture spotlight (employer branding) +Thursday: Data or trend analysis (authority) +Friday: Milestone, hiring, or community post (engagement) +``` + +**Sample company page posts**: + +**Tuesday -- Customer Use Case**: +``` +"We used to spend 3 hours every Monday pulling reports manually." + +That's what @CustomerName's ops team told us last quarter. + +After switching to [Product] automated workflows: +→ Report generation: 3 hours → 12 minutes +→ Data accuracy: 89% → 99.7% +→ Team freed up: 12 hours/week for strategic work + +The best part? They set it up in a single afternoon. + +Read the full story: [link in first comment] + +#DataAutomation #Operations #CustomerSuccess +``` + +**Wednesday -- Team Culture Spotlight**: +``` +This is Sarah. She joined us as intern #3 two years ago. + +Last week she deployed our new ML pipeline to production. +By herself. On a Tuesday. No drama. + +What happened in between: +→ Mentored by 4 different senior engineers +→ Shipped 47 PRs in her first year +→ Gave her first conference talk at 23 +→ Now leads a team of 3 + +We don't hire for credentials. +We hire for curiosity and grit. + +Sarah had both. + +We're hiring 5 more engineers just like her. +Link in the comments. + +#Hiring #Engineering #StartupCulture #WomenInTech +``` + +**Employee advocacy tracking**: +``` +| Employee | Role | Posts/Week | Avg Reach | Topics | +|----------|------|-----------|-----------|--------| +| CEO | Executive | 3 | 8,500 | Vision, industry, leadership | +| CTO | Executive | 2 | 5,200 | Technical, architecture, hiring | +| VP Eng | Leader | 2 | 3,100 | Engineering culture, management | +| DevRel | IC | 3 | 4,800 | Tutorials, product, community | +``` + +**Analytics tracking cadence**: +``` +Daily: Check post-level engagement (reactions, comments, shares) +Weekly: Follower growth, top-performing post, engagement rate trend +Monthly: Content audit — which pillars/formats performed best + Adjust next month's content mix based on data +Quarterly: Competitor benchmarking, SSI review, strategy refresh +``` + +### Example 3: Job Seeker Profile Optimization Campaign + +**Scenario**: Senior developer transitioning to engineering management role. + +**4-week content plan**: +``` +Week 1: Establish expertise + - Post about a technical decision you led and its business impact + - Share a "lessons from my first year managing" story + - Comment on 10 engineering leadership posts + +Week 2: Demonstrate thought leadership + - Publish a how-to post: "How I transitioned from IC to manager" + - Share data or a framework you've developed + - Start engaging with hiring managers' content in target companies + +Week 3: Build social proof + - Post about a mentoring success story (tag the mentee with permission) + - Share a "things I wish I knew" post targeting new managers + - Request 3-5 recommendations from colleagues and reports + +Week 4: Signal availability + - Post about what you're looking for (without desperation) + - Engage heavily in target company employees' content + - Send personalized connection requests to hiring managers +``` + +**Sample "open to opportunities" post**: +``` +After 8 years of writing code and 2 years of leading teams, +I'm looking for my next engineering management challenge. + +What I bring to the table: +→ Scaled a team from 4 to 22 engineers +→ Reduced deployment failures by 73% through better process +→ Mentored 6 engineers into senior roles +→ Built hiring pipelines that maintained 85%+ offer acceptance + +What I'm looking for: +→ Series A-C company building something meaningful +→ Team of 8-20 engineers who care about craft +→ Leadership that values engineering culture, not just velocity + +If your team is growing and you value +managers who still understand the code -- +I'd love to chat. + +DMs are open. Or drop a comment and I'll reach out. + +#OpenToWork #EngineeringManager #Hiring #Leadership +``` +>>>>>>> e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) diff --git a/hands/reddit/HAND.toml b/hands/reddit/HAND.toml index eb78b78..69b306f 100644 --- a/hands/reddit/HAND.toml +++ b/hands/reddit/HAND.toml @@ -205,6 +205,67 @@ label = "Up to 5 levels deep" value = "unlimited" label = "Any depth" +[[settings]] +key = "daily_comment_limit" +label = "Daily Comment Limit" +description = "Maximum number of comments to post per day across all subreddits (prevents spam-filter triggers)" +setting_type = "select" +default = "10" + +[[settings.options]] +value = "5" +label = "5 per day (conservative)" + +[[settings.options]] +value = "10" +label = "10 per day (balanced)" + +[[settings.options]] +value = "20" +label = "20 per day (active)" + +[[settings.options]] +value = "50" +label = "50 per day (high volume)" + +[[settings]] +key = "content_filter" +label = "Content Filter" +description = "Filter level for topics the Hand will engage with — strict avoids controversial or NSFW content" +setting_type = "select" +default = "strict" + +[[settings.options]] +value = "strict" +label = "Strict (skip NSFW, politics, controversial)" + +[[settings.options]] +value = "moderate" +label = "Moderate (skip NSFW only)" + +[[settings.options]] +value = "permissive" +label = "Permissive (engage with any allowed content)" + +[[settings]] +key = "authenticity_mode" +label = "Authenticity Mode" +description = "Strategy for maintaining human-like engagement patterns to avoid bot detection" +setting_type = "select" +default = "cautious" + +[[settings.options]] +value = "cautious" +label = "Cautious (randomized timing, varied phrasing, low volume)" + +[[settings.options]] +value = "balanced" +label = "Balanced (natural cadence, moderate volume)" + +[[settings.options]] +value = "transparent" +label = "Transparent (bot disclosure in profile, higher volume)" + # ─── Agent configuration ───────────────────────────────────────────────────── [agent] @@ -216,7 +277,7 @@ model = "default" max_tokens = 16384 temperature = 0.7 max_iterations = 50 -system_prompt = """You are Reddit Hand — an autonomous Reddit community manager that monitors subreddits, creates content, engages in discussions, and tracks engagement metrics. +system_prompt = """You are Reddit Hand — an autonomous Reddit community manager that monitors subreddits, creates content, engages in discussions, and tracks engagement metrics. Reddit communities are hostile to bots and low-effort automation. Your primary objective is to provide genuine value through every interaction while protecting account health. ## Phase 0 — Platform Detection & API Initialization (ALWAYS DO THIS FIRST) @@ -238,13 +299,14 @@ Note: This is app-only authentication — most read endpoints work, but posting Recover state: 1. memory_recall `reddit_hand_state` — load previous monitoring history and stats -2. Read **Hand Settings** for subreddits, monitor_mode, content_style, approval_mode, etc. +2. Read **Hand Settings** for subreddits, monitor_mode, content_style, approval_mode, daily_comment_limit, content_filter, authenticity_mode, etc. 3. file_read `reddit_queue.json` if it exists — pending posts/replies 4. knowledge_query for previously tracked threads and engagement data +5. memory_recall `reddit_hand_health` — load shadowban status, removal history, rate-limit incidents --- -## Phase 1 — Subreddit Rules & Monitoring +## Phase 1 — Subreddit Rules & Deep Culture Analysis Before monitoring, fetch and parse each subreddit's rules: ``` @@ -260,13 +322,50 @@ curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ "https://oauth.reddit.com/r/SUBREDDIT/about" \ -o subreddit_about.json ``` -For each subreddit, extract and store: -- Required flair options (if any) -- Posting restrictions (text-only, link-only, both) -- Self-promotion rules and ratio requirements -- Minimum account age or karma requirements -- Banned topics or content types -Store rules in the knowledge graph so they persist across sessions. + +### Concrete Rule Parsing + +For each subreddit, extract and classify rules into these categories: + +**Category A — Hard constraints (violation = removal/ban):** +- Required post flair (parse `link_flair_v2` endpoint; if flair list is non-empty and `link_flair_required` is true, MUST set flair on every post) +- Posting format restrictions (`submission_type`: "self" = text-only, "link" = links-only, "any" = both) +- Banned content types (look for rules mentioning "no memes", "no screenshots", "no AI-generated content") +- Account requirements (parse `comment_score_hide_mins`, check rules text for "minimum X days old" or "minimum X karma") +- Whitelisted domains (some subreddits only allow links from approved domains) + +**Category B — Soft constraints (violation = downvotes/mod warning):** +- Self-promotion ratio (common: "9:1 rule" or "10:1 ratio" — look for these patterns in rules text) +- Title formatting (e.g., r/AskReddit requires "?" ending; r/ELI5 requires "ELI5:" prefix; r/todayilearned requires "TIL" prefix) +- Required disclosures (e.g., "must disclose if you are affiliated") +- Engagement expectations (e.g., "OP must respond to comments within 1 hour" on some Q&A subreddits) + +**Category C — Cultural norms (violation = poor reception):** +- Tone expectations (fetch top 10 hot posts, analyze language style — technical vs casual vs meme-heavy) +- Average post length (short titles with long bodies? Long titles with no body?) +- Comment style (one-liners vs detailed responses) +- Upvote/downvote patterns (what gets rewarded vs penalized) + +**Example rule parsing for r/python:** +``` +Rule text: "All posts require flair. Self-promotional content is limited to 10% of activity." +→ Hard constraint: flair_required = true, fetch flair IDs from /api/link_flair_v2 +→ Soft constraint: self_promo_ratio = 10:1 +→ Action: Before posting, verify flair_id is set. Check recent 20 posts/comments to ensure promo ratio is met. +``` + +**Example rule parsing for r/AskReddit:** +``` +Rule text: "Rule 1: Must be a question. Rule 2: No text box." +→ Hard constraint: title must end with "?", selftext must be empty +→ Action: Generate title as question. Set kind=self with empty text body. +``` + +Store parsed rules in the knowledge graph with subreddit name as entity, categorized by A/B/C. + +--- + +## Phase 2 — Monitoring & Engagement Scoring Monitor configured subreddits for relevant content: ``` @@ -276,99 +375,221 @@ curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ -o subreddit_hot.json ``` -For each post, extract: title, selftext, author, score, num_comments, created_utc, permalink. +For each post, extract: title, selftext, author, score, num_comments, created_utc, permalink, upvote_ratio, link_flair_text, over_18. -Identify posts worth engaging with based on: -- Relevance to configured topics -- Post age (prefer fresh posts for visibility) -- Engagement potential (questions, discussions) -- Score trajectory (rising posts) -- Compliance with subreddit rules +### Content Filter Check -Rate each post's engagement potential: -- **High relevance (engage)**: Directly matches configured topics, <2 hours old, rising score, open question -- **Medium relevance (consider)**: Tangentially related, moderate age, decent engagement -- **Low relevance (skip)**: Off-topic, old, or already has 100+ comments (your reply won't be seen) -Only engage with High and Medium posts. Skip Low entirely. +Apply the `content_filter` setting before scoring: +- **strict**: Skip any post where `over_18=true`, or title/body contains political keywords, or subreddit is marked NSFW +- **moderate**: Skip only `over_18=true` posts +- **permissive**: No content filtering (but still respect subreddit rules) -Store interesting posts in knowledge graph for tracking. +### Engagement Scoring (0-100) + +Score each post using this formula: + +| Factor | Weight | Scoring | +|--------|--------|---------| +| Topic relevance | 30% | 0-100 based on keyword match + semantic similarity to configured topics | +| Freshness | 25% | 100 if <30 min old, 75 if <1h, 50 if <2h, 25 if <4h, 0 if >6h | +| Engagement potential | 20% | Questions=80, discussions=60, news=40, memes=20 | +| Visibility opportunity | 15% | 100 if <10 comments, 60 if 10-30, 30 if 30-60, 0 if >100 | +| Score trajectory | 10% | 100 if upvote_ratio>0.9, 50 if 0.7-0.9, 0 if <0.5 | + +**Action thresholds:** +- Score >= 65: ENGAGE — generate a reply (subject to daily_comment_limit) +- Score 40-64: QUEUE_FOR_REVIEW — save to queue with score and reasoning +- Score < 40: SKIP — log but do not engage + +Only engage with posts that pass ALL of: +1. Engagement score >= threshold +2. Post is not locked, removed, or archived +3. Content filter check passes +4. Daily comment limit not exhausted +5. Subreddit hard constraints are met + +Store scored posts in knowledge graph for pattern analysis. --- -## Phase 2 — Content Creation +## Phase 3 — Content Creation with Quality Checks When creating original posts: -1. Research trending topics in target subreddits -2. Check subreddit rules (sidebar) before posting -3. Create content matching the configured `content_style` -4. Follow Reddit etiquette — no spam, no self-promotion abuse +1. Research trending topics in target subreddits using /r/SUBREDDIT/hot and /r/SUBREDDIT/rising +2. Verify compliance with ALL Category A rules from Phase 1 (flair, format, domains) +3. Check Category B soft constraints (self-promo ratio, title format) +4. Create content matching the configured `content_style` -Post types to rotate: -- **Discussion**: Ask a thought-provoking question -- **Resource sharing**: Share useful links with commentary -- **How-to/Guide**: Detailed walkthrough on a topic -- **Analysis**: Data-driven breakdown of a topic +### Post Types (rotate to avoid pattern detection): +- **Discussion**: Ask a thought-provoking question grounded in a specific experience or data point +- **Resource sharing**: Share a useful link with 3+ sentences of original commentary explaining why it matters +- **How-to/Guide**: Step-by-step walkthrough tested against the subreddit's depth expectations +- **Analysis**: Data-driven breakdown with specific numbers, sources, and methodology + +### Content Quality Checklist (MUST pass all before posting): +1. [ ] Title matches subreddit formatting conventions (check top 10 posts for pattern) +2. [ ] Body length matches subreddit norms (check median body length of recent successful posts) +3. [ ] No generic filler phrases ("In this post I will discuss...", "Let me share my thoughts on...") +4. [ ] Contains at least one specific detail, number, or personal experience +5. [ ] Flair is set if required (with correct flair_id from API) +6. [ ] Self-promotion ratio is maintained if applicable +7. [ ] No duplicate or near-duplicate of a post made in the last 30 days (search first) +8. [ ] Passes the "would a real person post this?" test — if the post reads like AI boilerplate, rewrite it + +### Cross-Subreddit Content Adaptation +When posting about the same topic in multiple subreddits: +- NEVER copy-paste the same content — write fresh for each community +- Adapt vocabulary: r/programming expects code examples, r/technology expects impact framing, r/startups expects business context +- Adjust length: niche subreddits reward depth (500+ words), large subreddits reward conciseness (150-250 words) +- Use subreddit-specific references: mention past popular posts in that community, reference their inside jokes or running themes --- -## Phase 3 — Engagement +## Phase 4 — Engagement & Authenticity Protection If `auto_reply` is enabled: 1. Read new comments on monitored threads 2. Generate contextually relevant, helpful replies -3. Match the subreddit's communication style +3. Match the subreddit's communication style (analyze 5 top-voted comments for tone) 4. Add genuine value — never generic "Great post!" responses -Reply guidelines: -- Be genuinely helpful and add new information -- Cite sources when making claims -- Respect the community's norms and rules -- NEVER argue aggressively or engage with trolls -- NEVER post spam or repetitive content +### Reply Quality Guidelines: +- Open with a direct answer or specific reaction to the post's main point +- Include personal experience, a source link, or a concrete example +- Ask a follow-up question to invite continued discussion +- Vary sentence structure and length — monotonous patterns signal automation +- Use subreddit-appropriate vocabulary (contractions in casual subs, formal language in academic subs) +- NEVER use the same opening phrase twice in the same session +- NEVER argue aggressively or engage with trolls — disengage silently +- NEVER post spam, repetitive content, or template-style responses + +### Authenticity Mode Behaviors: +Based on the `authenticity_mode` setting: + +**Cautious mode:** +- Add random delays of 2-8 minutes between comments (never post two comments within 60 seconds) +- Vary comment length significantly (some 2 sentences, some 2 paragraphs) +- Skip some good engagement opportunities randomly (engage with ~60% of qualifying posts) +- Occasionally upvote posts without commenting +- Never post at perfectly regular intervals + +**Balanced mode:** +- Add 1-3 minute delays between comments +- Maintain natural length variation +- Engage with ~80% of qualifying posts + +**Transparent mode:** +- Include bot disclosure in account profile/bio (not in every comment) +- No artificial delays +- Engage with all qualifying posts up to daily limit + +### Comment Removal Pattern Recognition: +After posting, check if your comments are still visible: +``` +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/comments/POST_ID" +``` +If your comment does not appear in the response within 5 minutes of posting: +1. Log the removal event with subreddit, post content, and timestamp +2. Increment the removal counter for that subreddit +3. If 3+ comments removed from the same subreddit in 24 hours → PAUSE posting there and alert user +4. Analyze removed comment patterns — look for common triggers (links, keywords, length) --- -## Phase 4 — Queue Management +## Phase 5 — Shadowban Detection & Account Health + +### Shadowban Detection Protocol + +A shadowban means your posts/comments are invisible to others but appear normal to you. Check regularly: + +**Method 1 — Profile accessibility check:** +``` +curl -s -A "LibreFang Reddit Hand/1.0" \ + "https://www.reddit.com/user/YOUR_USERNAME/about.json" +``` +If this returns 404 or empty while the account exists, the account is likely shadowbanned. + +**Method 2 — Comment visibility check:** +After posting a comment, wait 2 minutes, then fetch the thread without authentication: +``` +curl -s -A "LibreFang Reddit Hand/1.0" \ + "https://www.reddit.com/r/SUBREDDIT/comments/POST_ID.json" +``` +Search for your comment in the response. If absent, it is invisible to others. + +**Method 3 — Track removal rate:** +If more than 50% of comments posted in the last 24 hours are invisible → likely shadowbanned. + +### Shadowban Response Protocol: +1. IMMEDIATELY stop all posting and commenting +2. memory_store `reddit_hand_health` with `shadowban_detected: true, detected_at: TIMESTAMP` +3. event_publish "reddit_shadowban_detected" with details +4. Alert the user with specific evidence (which comments are invisible, removal rate) +5. Do NOT attempt to circumvent the ban — this violates Reddit TOS + +### Ongoing Account Health Monitoring: +Track these metrics every session: +- **Comment removal rate**: (removed comments / total comments) per subreddit — healthy is <5% +- **Karma velocity**: Net karma change per day — declining trend is a warning +- **Rate limit frequency**: How often 429 responses occur — increasing frequency suggests Reddit is throttling +- **Comment score distribution**: If >30% of recent comments score 0 or below, content strategy needs revision +- **Post removal rate**: If >20% of posts are removed, subreddit rule compliance is failing + +Store health metrics in memory for trend analysis across sessions. + +--- + +## Phase 6 — Queue Management If `approval_mode` is ENABLED: -1. Write generated posts/replies to `reddit_queue.json` +1. Write generated posts/replies to `reddit_queue.json` with engagement score, target subreddit, and rule compliance notes 2. Write a human-readable `reddit_queue_preview.md` for review 3. event_publish "reddit_queue_updated" with queue size 4. Do NOT post — wait for user approval If `approval_mode` is DISABLED: 1. Post content via the Reddit API -2. Log all posts to `reddit_posted.json` -3. Respect rate limits (10 requests per minute for OAuth) +2. Enforce `daily_comment_limit` — track count in memory, refuse to post beyond limit +3. Log all posts to `reddit_posted.json` with timestamp, subreddit, and content hash +4. Respect rate limits (10 requests per minute for OAuth) +5. Verify each post is visible after 2 minutes (Phase 4 removal check) --- -## Phase 5 — Performance Tracking +## Phase 7 — Performance Tracking Track engagement metrics: - Post karma and comment karma changes - Reply engagement (upvotes on your comments) - Thread growth on posts you created -- Community reception patterns +- Community reception patterns per subreddit +- Comment removal rate trends +- Engagement score accuracy (did high-scored posts actually perform well?) Store insights in knowledge graph for content optimization. ### Monitoring Loop Exit Criteria Stop the monitoring loop when ANY of these conditions is met: -1. **No relevant posts**: 5 consecutive monitoring cycles found 0 posts worth engaging with +1. **No relevant posts**: 5 consecutive monitoring cycles found 0 posts with engagement score >= 40 2. **Rate limited**: Reddit API returns 429 — back off for the Retry-After period 3. **Queue full**: Approval queue has 10+ pending items — stop generating until user reviews -4. **Karma declining**: Net karma from recent posts is negative — pause and alert user for strategy review +4. **Karma declining**: Net karma from recent posts is negative over 3+ days — pause and alert user for strategy review 5. **Iteration cap**: 20+ monitoring iterations in a single session — save state and exit +6. **Daily limit reached**: `daily_comment_limit` exhausted — save state and wait for next day +7. **Health alert**: Shadowban detected or removal rate >30% — stop immediately +8. **Consecutive removals**: 3+ comments removed in a row — pause and alert user --- -## Phase 6 — State Persistence +## Phase 8 — State Persistence 1. Save queue to `reddit_queue.json` 2. Save posting history to `reddit_posted.json` -3. memory_store `reddit_hand_state`: last_run, posts_created, replies_sent, karma_tracked -4. Update dashboard stats: +3. memory_store `reddit_hand_state`: last_run, posts_created, replies_sent, karma_tracked, daily_comments_used +4. memory_store `reddit_hand_health`: removal_rate, shadowban_status, rate_limit_incidents, karma_velocity +5. Update dashboard stats: - memory_store `reddit_hand_posts_created` — total posts - memory_store `reddit_hand_replies_sent` — total replies - memory_store `reddit_hand_queue_size` — current queue size @@ -378,16 +599,22 @@ Stop the monitoring loop when ANY of these conditions is met: ## Guidelines -- ALWAYS respect subreddit rules — read the sidebar before posting +- ALWAYS respect subreddit rules — parse and store them BEFORE posting (Phase 1) +- ALWAYS check content quality checklist before posting (Phase 3) +- ALWAYS verify comment visibility after posting (Phase 4) +- ALWAYS run shadowban detection at session start and after every 10 comments (Phase 5) - NEVER post spam, self-promotion abuse, or vote manipulation - NEVER harass, bully, or engage in bad-faith arguments -- NEVER impersonate other users +- NEVER impersonate other users or pretend to be human when directly asked - NEVER post private or confidential information +- NEVER exceed the `daily_comment_limit` setting +- NEVER post in a subreddit where removal rate exceeds 30% - Respect Reddit's API rate limits (10 req/min for OAuth, 30 req/min with user auth) - In `approval_mode` (default), ALWAYS write to queue — NEVER post without review - If the API returns an error, log it and retry once — then skip and alert the user -- Adapt tone to each subreddit's culture -- When in doubt about a post, queue it for review with a note +- Adapt tone to each subreddit's culture through analysis, not assumptions +- When in doubt about a post, queue it for review with a note explaining the concern +- Prioritize account longevity over short-term engagement — a banned account produces zero value """ [dashboard] @@ -433,6 +660,7 @@ default_active = false [i18n.zh] name = "Reddit Hand" description = "自主 Reddit 管理——监控子版块、发布内容、回复帖子并追踪 Karma 和互动" +<<<<<<< HEAD category = "通信" [i18n.zh.settings.subreddits] @@ -661,3 +889,306 @@ description = "계정이 최소 이만큼의 카르마를 보유한 서브레딧 [i18n.ko.settings.max_reply_depth] label = "최대 답글 깊이" description = "답글 작성의 최대 댓글 중첩 깊이 (깊은 중첩일수록 노출도 감소)" +||||||| parent of e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) +======= +category = "通信" + +[i18n.zh.settings.subreddits] +label = "子版块" +description = "要监控的子版块列表(逗号分隔,例如 rust,programming,machinelearning)" + +[i18n.zh.settings.monitor_mode] +label = "监控模式" +description = "在监控的子版块中追踪哪些内容" + +[i18n.zh.settings.auto_reply] +label = "自动回复" +description = "自动回复相关的帖子和评论" + +[i18n.zh.settings.post_frequency] +label = "发布频率" +description = "创建原创帖子的频率" + +[i18n.zh.settings.content_style] +label = "内容风格" +description = "帖子和回复的语气和风格" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将帖子和回复加入队列等待审核,而非直接发布" + +[i18n.zh.settings.min_karma_to_post] +label = "最低发帖 Karma" +description = "仅在账户拥有至少此数量 Karma 的子版块中发帖" + +[i18n.zh.settings.max_reply_depth] +label = "最大回复深度" +description = "回复的最大评论嵌套深度(深层嵌套的可见度较低)" + +[i18n.zh.settings.daily_comment_limit] +label = "每日评论上限" +description = "每天在所有子版块中发布评论的最大数量(防止触发垃圾过滤器)" + +[i18n.zh.settings.content_filter] +label = "内容过滤" +description = "参与话题的过滤级别——严格模式会跳过争议性和 NSFW 内容" + +[i18n.zh.settings.authenticity_mode] +label = "真实性模式" +description = "维持类人互动模式以避免机器人检测的策略" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Reddit" +description = "Gestor autónomo de Reddit — monitorea subreddits, publica contenido, responde en hilos y rastrea karma e interacciones" +category = "Comunicación" + +[i18n.es.settings.subreddits] +label = "Subreddits" +description = "Lista de subreddits a monitorear separados por comas (ej. rust,programming,machinelearning)" + +[i18n.es.settings.monitor_mode] +label = "Modo de monitoreo" +description = "Qué rastrear en los subreddits monitoreados" + +[i18n.es.settings.auto_reply] +label = "Respuesta automática" +description = "Responder automáticamente a publicaciones y comentarios relevantes" + +[i18n.es.settings.post_frequency] +label = "Frecuencia de publicación" +description = "Con qué frecuencia crear publicaciones originales" + +[i18n.es.settings.content_style] +label = "Estilo de contenido" +description = "Tono y enfoque para publicaciones y respuestas" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Poner publicaciones y respuestas en cola para revisión en lugar de publicarlas directamente" + +[i18n.es.settings.min_karma_to_post] +label = "Karma mínimo para publicar" +description = "Solo publicar en subreddits donde la cuenta tenga al menos este nivel de karma" + +[i18n.es.settings.max_reply_depth] +label = "Profundidad máxima de respuesta" +description = "Profundidad máxima del hilo de comentarios para responder (los hilos más profundos tienen menos visibilidad)" + +[i18n.es.settings.daily_comment_limit] +label = "Límite diario de comentarios" +description = "Número máximo de comentarios por día en todos los subreddits (evita activar filtros de spam)" + +[i18n.es.settings.content_filter] +label = "Filtro de contenido" +description = "Nivel de filtrado de temas — el modo estricto omite contenido NSFW, político o controvertido" + +[i18n.es.settings.authenticity_mode] +label = "Modo de autenticidad" +description = "Estrategia para mantener patrones de interacción similares a los humanos y evitar la detección de bots" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "Reddit Hand" +description = "自律型Redditマネージャー——サブレディットの監視、コンテンツ投稿、スレッドへの返信、Karmaとエンゲージメントの追跡" +category = "コミュニケーション" + +[i18n.ja.settings.subreddits] +label = "サブレディット" +description = "監視するサブレディットのリスト(カンマ区切り、例: rust,programming,machinelearning)" + +[i18n.ja.settings.monitor_mode] +label = "監視モード" +description = "監視対象のサブレディットで追跡する内容" + +[i18n.ja.settings.auto_reply] +label = "自動返信" +description = "関連する投稿やコメントに自動で返信する" + +[i18n.ja.settings.post_frequency] +label = "投稿頻度" +description = "オリジナル投稿を作成する頻度" + +[i18n.ja.settings.content_style] +label = "コンテンツスタイル" +description = "投稿と返信のトーンとアプローチ" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "投稿や返信を直接公開せず、レビュー用キューに追加する" + +[i18n.ja.settings.min_karma_to_post] +label = "投稿に必要な最低Karma" +description = "アカウントが最低このKarmaを持つサブレディットでのみ投稿する" + +[i18n.ja.settings.max_reply_depth] +label = "最大返信深度" +description = "返信するコメントスレッドの最大ネスト深度(深いスレッドほど可視性が低い)" + +[i18n.ja.settings.daily_comment_limit] +label = "1日のコメント上限" +description = "全サブレディットで1日に投稿するコメントの最大数(スパムフィルターの誤検知を防止)" + +[i18n.ja.settings.content_filter] +label = "コンテンツフィルター" +description = "参加するトピックのフィルターレベル — 厳格モードではNSFW・政治・物議を醸すコンテンツをスキップ" + +[i18n.ja.settings.authenticity_mode] +label = "真正性モード" +description = "ボット検出を回避するための人間らしいエンゲージメントパターン維持戦略" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Reddit" +description = "Gestionnaire Reddit autonome — surveille les subreddits, publie du contenu, répond dans les fils et suit le karma et l'engagement" +category = "Communication" + +[i18n.fr.settings.subreddits] +label = "Subreddits" +description = "Liste de subreddits à surveiller séparés par des virgules (ex. rust,programming,machinelearning)" + +[i18n.fr.settings.monitor_mode] +label = "Mode de surveillance" +description = "Ce qu'il faut suivre dans les subreddits surveillés" + +[i18n.fr.settings.auto_reply] +label = "Réponse automatique" +description = "Répondre automatiquement aux publications et commentaires pertinents" + +[i18n.fr.settings.post_frequency] +label = "Fréquence de publication" +description = "Fréquence de création de publications originales" + +[i18n.fr.settings.content_style] +label = "Style de contenu" +description = "Ton et approche pour les publications et réponses" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Mettre les publications et réponses en file d'attente pour révision au lieu de les publier directement" + +[i18n.fr.settings.min_karma_to_post] +label = "Karma minimum pour publier" +description = "Ne publier que dans les subreddits où le compte possède au moins ce niveau de karma" + +[i18n.fr.settings.max_reply_depth] +label = "Profondeur maximale de réponse" +description = "Profondeur maximale d'imbrication des commentaires pour répondre (les fils plus profonds ont moins de visibilité)" + +[i18n.fr.settings.daily_comment_limit] +label = "Limite quotidienne de commentaires" +description = "Nombre maximum de commentaires par jour sur tous les subreddits (empêche le déclenchement des filtres anti-spam)" + +[i18n.fr.settings.content_filter] +label = "Filtre de contenu" +description = "Niveau de filtrage des sujets — le mode strict ignore le contenu NSFW, politique ou controversé" + +[i18n.fr.settings.authenticity_mode] +label = "Mode d'authenticité" +description = "Stratégie pour maintenir des modèles d'interaction humains et éviter la détection automatique" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Reddit-Hand" +description = "Autonomer Reddit-Manager — überwacht Subreddits, postet Inhalte, antwortet in Threads und verfolgt Karma und Engagement" +category = "Kommunikation" + +[i18n.de.settings.subreddits] +label = "Subreddits" +description = "Kommagetrennte Liste der zu überwachenden Subreddits (z.B. rust,programming,machinelearning)" + +[i18n.de.settings.monitor_mode] +label = "Überwachungsmodus" +description = "Was in den überwachten Subreddits verfolgt werden soll" + +[i18n.de.settings.auto_reply] +label = "Automatische Antwort" +description = "Automatisch auf relevante Beiträge und Kommentare antworten" + +[i18n.de.settings.post_frequency] +label = "Veröffentlichungshäufigkeit" +description = "Wie oft originale Beiträge erstellt werden" + +[i18n.de.settings.content_style] +label = "Inhaltsstil" +description = "Ton und Ansatz für Beiträge und Antworten" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Beiträge und Antworten zur Überprüfung in die Warteschlange stellen, anstatt sie direkt zu veröffentlichen" + +[i18n.de.settings.min_karma_to_post] +label = "Mindest-Karma zum Posten" +description = "Nur in Subreddits posten, in denen das Konto mindestens dieses Karma-Level hat" + +[i18n.de.settings.max_reply_depth] +label = "Maximale Antworttiefe" +description = "Maximale Verschachtelungstiefe für Kommentarantworten (tiefere Threads haben geringere Sichtbarkeit)" + +[i18n.de.settings.daily_comment_limit] +label = "Tägliches Kommentarlimit" +description = "Maximale Anzahl an Kommentaren pro Tag in allen Subreddits (verhindert Auslösung von Spamfiltern)" + +[i18n.de.settings.content_filter] +label = "Inhaltsfilter" +description = "Filterstufe für Themen — der strikte Modus überspringt NSFW-, politische und kontroverse Inhalte" + +[i18n.de.settings.authenticity_mode] +label = "Authentizitätsmodus" +description = "Strategie zur Aufrechterhaltung menschlicher Interaktionsmuster zur Vermeidung von Bot-Erkennung" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "Reddit Hand" +description = "자율 Reddit 관리 — 서브레딧 모니터링, 콘텐츠 게시, 스레드 댓글 및 카르마와 참여도 추적" +category = "커뮤니케이션" + +[i18n.ko.settings.subreddits] +label = "서브레딧" +description = "모니터링할 서브레딧 목록 (쉼표로 구분, 예: rust,programming,machinelearning)" + +[i18n.ko.settings.monitor_mode] +label = "모니터링 모드" +description = "모니터링 대상 서브레딧에서 추적할 콘텐츠" + +[i18n.ko.settings.auto_reply] +label = "자동 답글" +description = "관련 게시물과 댓글에 자동으로 답글 작성" + +[i18n.ko.settings.post_frequency] +label = "게시 빈도" +description = "원본 게시물 작성 주기" + +[i18n.ko.settings.content_style] +label = "콘텐츠 스타일" +description = "게시물과 답글의 어조와 접근 방식" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "게시물과 답글을 직접 게시하지 않고 대기열에 추가하여 검토" + +[i18n.ko.settings.min_karma_to_post] +label = "최소 게시 카르마" +description = "계정이 최소 이만큼의 카르마를 보유한 서브레딧에서만 게시" + +[i18n.ko.settings.max_reply_depth] +label = "최대 답글 깊이" +description = "답글 작성의 최대 댓글 중첩 깊이 (깊은 중첩일수록 노출도 감소)" + +[i18n.ko.settings.daily_comment_limit] +label = "일일 댓글 제한" +description = "모든 서브레딧에서 하루에 게시할 수 있는 최대 댓글 수 (스팸 필터 트리거 방지)" + +[i18n.ko.settings.content_filter] +label = "콘텐츠 필터" +description = "참여할 주제의 필터 수준 — 엄격 모드는 NSFW, 정치, 논란이 되는 콘텐츠를 건너뜁니다" + +[i18n.ko.settings.authenticity_mode] +label = "진정성 모드" +description = "봇 탐지를 피하기 위한 인간과 유사한 상호작용 패턴 유지 전략" +>>>>>>> e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) diff --git a/hands/reddit/SKILL.md b/hands/reddit/SKILL.md index fe167b8..1c833fa 100644 --- a/hands/reddit/SKILL.md +++ b/hands/reddit/SKILL.md @@ -162,10 +162,12 @@ Different subreddits enforce very different rules. Here are real examples: Before posting or replying, scan for these red flags: - **Thread locked or removed** — moderators already intervened, do NOT engage -- **Controversial marker** (†) on comments — indicates divisive topic, tread carefully +- **Controversial marker** (dagger symbol) on comments — indicates divisive topic, tread carefully - **OP deleted account** — thread may be abandoned or toxic - **Heavily downvoted parent** — replying to a -10 comment rarely goes well - **Personal attacks in thread** — disengage entirely, do not escalate +- **Moderator stickied warning** — check the first comment for mod notices ("reminder: be civil", "this thread is being monitored") +- **Rapid comment deletion** — if many comments in a thread show as [deleted], moderators are actively pruning; avoid posting When generating replies, NEVER: - Take sides in heated debates — provide balanced perspectives @@ -173,6 +175,72 @@ When generating replies, NEVER: - Correct grammar/spelling unless directly relevant to the discussion - Reply to comments that are clearly trolling or bad-faith +### Bot Detection & Shadowban Avoidance + +Reddit communities and moderators are increasingly hostile to automated accounts. Bot detection works through behavioral patterns, not just content analysis. + +**Common bot detection signals (avoid ALL of these):** + +| Signal | Why It Triggers Detection | Mitigation | +|--------|--------------------------|------------| +| Regular posting intervals | Humans do not post every exactly 60 minutes | Randomize intervals: base + random(0, base*0.5) | +| Identical phrasing patterns | Repeating "Great question! Here's what I think..." | Maintain a list of 20+ opening variations, never reuse within a session | +| Rapid-fire comments | 5 comments in 3 minutes is inhuman | Minimum 2-minute gap between comments, randomize up to 8 minutes | +| No voting activity | Real users upvote/downvote regularly | Occasionally upvote posts you read but do not comment on | +| Perfect grammar every time | Real users make typos, use slang | Match the subreddit's casualness level — contractions, incomplete sentences are fine | +| Only top-level comments | Bots often do not engage in back-and-forth | Reply to replies on your comments to build conversation threads | +| Activity only during business hours | Suggests automation on a cron schedule | Vary session times if possible | +| No post history variety | Only posting in 1-2 subreddits | Engage in 3-5 subreddits minimum | + +**Shadowban indicators and detection:** + +A shadowban means your content is invisible to others. Check for: +1. **Profile 404**: `https://www.reddit.com/user/USERNAME/about.json` returns 404 when accessed without your auth token +2. **Comment invisibility**: Your comment does not appear in the thread when fetched anonymously (without Bearer token) +3. **Sudden zero engagement**: 5+ consecutive comments with 1 karma (only your own upvote) across different subreddits + +**If shadowban is detected:** +- STOP all posting immediately +- Do NOT create a new account (ban evasion violates Reddit TOS) +- Alert the user with evidence (which comments are invisible) +- User can appeal at https://www.reddit.com/appeals + +**Subreddit-level shadowban (AutoModerator filtering):** +Some subreddits use AutoModerator to silently remove posts from accounts that meet certain criteria (new accounts, low karma, specific keywords). Signs: +- Comment appears in your profile but not in the thread +- Only happens in specific subreddits (not site-wide) +- Resolution: Message the subreddit moderators via modmail to request approval + +### Comment Removal Pattern Recognition + +Track every comment/post for removal to identify problematic patterns: + +**Removal types:** +| Indicator | Meaning | Response | +|-----------|---------|----------| +| Comment shows as [removed] | Moderator removed it | Review subreddit rules; your content likely violated one | +| Comment shows as [deleted] | You deleted it (or account deleted) | N/A | +| Comment invisible (not in thread, no [removed]) | AutoModerator or spam filter | Likely keyword trigger or account-level filter | +| Post removed with no notification | Spam filter caught it | Too many links, title matched spam pattern, or account too new | + +**Building a removal pattern database:** +After each session, record removals: +``` +{ + "subreddit": "r/example", + "content_type": "comment", + "content_preview": "first 50 chars...", + "removal_type": "mod_removed | automod_filtered | spam_filtered", + "probable_cause": "contained link | keyword X | self-promo ratio", + "timestamp": "ISO8601" +} +``` +After 10+ data points, analyze for patterns: +- Which subreddits remove content most often? +- Which content types (links, long posts, short comments) get removed? +- Do specific keywords correlate with removal? +- Does time of day matter (some mod teams are more active at certain hours)? + ### Post Types That Perform Well | Type | Best For | Example | @@ -247,6 +315,7 @@ Monitor account standing: - Build karma organically through genuine engagement - Avoid posting too frequently (triggers spam filters) - Diversify activity across multiple subreddits +<<<<<<< HEAD --- @@ -1012,3 +1081,776 @@ ROI = (Value of outcomes - Total cost) / Total cost - [ ] Content planned: [description] - [ ] Threads to follow up on: [links] ``` +||||||| parent of e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) +======= + +--- + +## Worked Examples + +### Example 1: Product Launch on Reddit + +**Scenario**: You are launching a developer CLI tool and want to generate awareness on Reddit. + +**Phase 1 — Subreddit Research (Week 1-2 before launch)** + +Identify target subreddits and evaluate each: +``` +Target subreddits (prioritized): +1. r/commandline — 350k members, accepts tool announcements, requires demo/screenshot +2. r/programming — 5M members, strict anti-marketing, only accepts substantial technical posts +3. r/opensource — 200k members, friendly to launches, requires repo link +4. r/devtools — 50k members, niche but highly targeted +5. r/sideproject — 100k members, launch-friendly, expects "what I built" framing +``` + +Fetch subreddit rules programmatically: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/commandline/about/rules" +``` + +**Phase 2 — Karma Building (Week 1-2 before launch)** + +Before posting about your product, build credibility: +``` +Day 1-3: Answer questions in r/commandline and r/programming (3-5 helpful comments/day) +Day 4-7: Share a useful tip or short guide unrelated to your product +Day 8-10: Engage in discussions, upvote good content, reply to others' posts +Day 11-14: Share a technical deep-dive related to your product's domain (not the product itself) +``` + +**Phase 3 — Launch Posts (Launch Day)** + +Craft posts per subreddit culture: + +For **r/sideproject** (casual, story-driven): +``` +Title: "I built a CLI tool that does X — here's what I learned" +Body: +- Paragraph on the problem and motivation +- Short demo (gif/video link or code block) +- What went wrong during development +- Link to repo +- "Would love feedback on X" +``` + +For **r/programming** (technical, anti-fluff): +``` +Title: "X: an open-source CLI for Y written in Rust [with benchmarks]" +Body: +- Link directly to repo or blog post with technical depth +- Performance comparison table +- Architecture decisions +- NO "please star my repo" language +``` + +For **r/commandline** (practical, demo-focused): +``` +Title: "X — does Y in Z seconds from your terminal" +Body: +- Install instructions (one-liner) +- Usage example with real output +- Screenshot or asciinema link +- Comparison to existing tools +``` + +**Phase 4 — Engagement (Launch Day + 48 hours)** + +Response templates: + +| Comment Type | Response Strategy | +|-------------|-------------------| +| "How does this compare to Z?" | Honest comparison table, acknowledge Z's strengths | +| "Why not just use Z?" | Explain specific use cases where yours differs, no FUD | +| "Found a bug" | Thank them, ask for details, open GitHub issue immediately | +| "This is spam" | Do NOT argue. Briefly state this is your project and you're here to discuss | +| "Great work!" | Thank them, ask what feature they'd want next | +| Feature request | Acknowledge, add to roadmap, link to issue tracker | + +**Phase 5 — Follow-Up (Week after launch)** + +- Reply to every comment within 12 hours +- Post an update in r/sideproject if you hit a milestone (e.g., "Hit 500 stars, here's what I changed based on Reddit feedback") +- Do NOT cross-post the same content -- write fresh posts per subreddit + +--- + +### Example 2: Community Monitoring and Sentiment Tracking + +**Scenario**: You manage a brand's Reddit presence and need to track mentions, sentiment, and emerging issues. + +**Step 1 — Set Up Monitoring Queries** + +Search for brand mentions across Reddit: +```bash +# Search all of Reddit for brand mentions +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/search?q=%22BrandName%22+OR+%22brandname%22&sort=new&limit=25&t=day" +``` + +Monitor specific subreddits where your audience lives: +```bash +# Monitor r/technology for relevant topics +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/technology/search?q=BrandName&restrict_sr=on&sort=new&limit=25&t=week" +``` + +**Step 2 — Sentiment Classification** + +Categorize each mention into: +``` +POSITIVE — Praise, recommendation, success story +NEUTRAL — Factual mention, question, comparison +NEGATIVE — Complaint, bug report, frustration +CRITICAL — Security concern, viral complaint, legal risk +``` + +Scoring signals from Reddit data: +``` +score > 100 + sentiment=NEGATIVE → High-priority alert (viral complaint) +score > 50 + sentiment=POSITIVE → Amplification opportunity +num_comments > 20 + any sentiment → Active discussion, monitor closely +upvote_ratio < 0.5 → Controversial, may escalate +``` + +**Step 3 — Alert Thresholds** + +| Condition | Action | +|-----------|--------| +| CRITICAL mention with score > 10 | Immediate alert to team | +| 3+ NEGATIVE mentions in 24 hours | Trend alert, investigate root cause | +| NEGATIVE post in subreddit > 500k members | Monitor hourly for 48 hours | +| Competitor comparison post trending | Prepare factual response (do NOT post defensively) | + +**Step 4 — Weekly Report Template** + +``` +## Reddit Weekly Report — [Date Range] + +### Summary +- Total mentions: X (up/down Y% from last week) +- Sentiment breakdown: X% positive, Y% neutral, Z% negative +- Top subreddits: r/sub1 (N mentions), r/sub2 (N mentions) + +### Trending Topics +1. [Topic] — [Subreddit] — [Sentiment] — [Link] +2. ... + +### Action Items +- [ ] Respond to [specific thread] — negative sentiment, high visibility +- [ ] Engage with [specific thread] — positive, amplification opportunity + +### Competitor Activity +- [Competitor A]: N mentions, trending topics: ... +- [Competitor B]: N mentions, trending topics: ... + +### Metrics +| Metric | This Week | Last Week | Change | +|--------|-----------|-----------|--------| +| Total mentions | | | | +| Positive % | | | | +| Avg post score | | | | +| Response time (hrs) | | | | +``` + +--- + +### Example 3: AMA (Ask Me Anything) Management + +**Scenario**: You are organizing an AMA for a tech CEO in r/technology. + +**Preparation (2 Weeks Before)** + +1. Contact the subreddit moderators: + - Message the mod team through modmail (not individual DMs) + - Propose date, time, and AMA subject + - Ask about specific rules for AMAs (verification, scheduling, flair) + - Confirm the post format they expect + +2. Schedule for peak engagement: + ``` + Recommended AMA times (US-centric subreddits): + - Tuesday-Thursday, 11:00 AM - 1:00 PM EST + - Avoid: weekends, holidays, major news days + - Post the AMA thread 30-60 minutes before the host starts answering + ``` + +3. Prepare the AMA post: + ``` + Title: "I'm [Name], [Role] at [Company]. [One-line hook]. AMA!" + + Body: + - Brief intro (2-3 sentences about credentials) + - Why this AMA is happening (new product, milestone, event) + - Proof/verification (link to tweet, photo with timestamp) + - "I'll start answering at [TIME] [TIMEZONE]. Ask me anything!" + - Links to relevant context (website, blog post, prior work) + ``` + +**During the AMA (2-3 Hours)** + +Real-time engagement strategy: +``` +1. Sort comments by "best" and "new" alternately every 15 minutes +2. Answer top-voted questions first (these set the tone) +3. Answer at least 20-30 questions in a 2-hour session +4. Mix short answers with detailed ones — avoid walls of text for every question +5. Skip hostile/troll questions silently — do NOT acknowledge them +6. For tough questions: answer honestly or say "I can't discuss that yet" +7. Upvote good questions (even tough ones) — shows good faith +``` + +Response length guide: +| Question Type | Response Length | +|--------------|----------------| +| Simple factual | 1-2 sentences | +| Technical deep-dive | 2-3 paragraphs | +| Personal/funny | 1-2 sentences, match the tone | +| Critical/tough | 2-3 sentences, direct and honest | +| Off-topic | Brief redirect or polite decline | + +**Follow-Up (24-48 Hours After)** + +- Post an edit to the original AMA: "Thanks everyone! I answered [N] questions. Check back — I'll try to answer a few more this week." +- Answer 5-10 more highly-upvoted questions that were missed +- Share the AMA link on other platforms (Twitter, LinkedIn) to drive continued engagement +- Compile a "best of" summary with links to the strongest Q&A exchanges + +--- + +## Advanced API Patterns + +### Pagination Handling + +Reddit uses cursor-based pagination with `after` and `before` fullnames. + +**Paginate through subreddit posts**: +```bash +# Page 1 +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100" +# Response includes: "after": "t3_abc123" + +# Page 2 +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100&after=t3_abc123" +# Response includes: "after": "t3_def456" (or null if last page) + +# Page 3 +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100&after=t3_def456" +``` + +Pagination rules: +- `limit` max is 100 per request +- `after` returns items chronologically older than the given fullname +- `before` returns items chronologically newer (useful for "check for new posts since last poll") +- When `after` is `null` in the response, you have reached the last page +- Reddit caps listing depth at ~1000 items regardless of pagination + +**Paginate backward (newer items)**: +```bash +# Get posts newer than a known fullname +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=25&before=t3_abc123" +``` + +### Flair Management + +**Get available flairs for a subreddit**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/api/link_flair_v2" +``` + +**Submit a post with flair**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "sr=SUBREDDIT&kind=self&title=TITLE&text=BODY&flair_id=FLAIR_ID&flair_text=FLAIR_TEXT" \ + "https://oauth.reddit.com/api/submit" +``` + +**Set flair on an existing post** (requires mod or post author permissions): +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "link=t3_POST_ID&flair_template_id=FLAIR_ID" \ + "https://oauth.reddit.com/r/SUBREDDIT/api/selectflair" +``` + +### Moderation Endpoints + +These require moderator permissions on the target subreddit. + +**Get moderation queue**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about/modqueue?limit=25" +``` + +**Approve a post/comment**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "id=FULLNAME" \ + "https://oauth.reddit.com/api/approve" +``` + +**Remove a post/comment**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "id=FULLNAME&spam=false" \ + "https://oauth.reddit.com/api/remove" +``` + +**Get moderation log**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about/log?limit=25&type=removelink" +``` + +**Distinguish a comment as moderator**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "id=FULLNAME&how=yes" \ + "https://oauth.reddit.com/api/distinguish" +``` + +### Multi-Subreddit Monitoring + +**Monitor multiple subreddits in a single request**: +```bash +# Combine subreddits with "+" for a merged feed +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/python+rust+golang/new?limit=50" +``` + +**Search across multiple subreddits**: +```bash +# Use the subreddit field in search to restrict +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/search?q=BrandName+subreddit%3Apython+OR+subreddit%3Arust&sort=new&limit=25" +``` + +**Get subreddit metadata for comparison**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about" +``` +Key fields in response: `subscribers`, `active_user_count`, `created_utc`, `public_description`, `submit_text`, `submission_type`. + +### Polling Strategies for Real-Time Awareness + +Reddit has no webhook support. Use polling with these patterns: + +**Efficient polling loop**: +``` +1. Fetch /r/SUBREDDIT/new?limit=10 every 60 seconds +2. Store the fullname of the newest item seen +3. On next poll, use ?before=LAST_SEEN_FULLNAME to get only new items +4. If response is empty, no new posts — sleep and retry +5. If response has items, process them and update LAST_SEEN_FULLNAME +``` + +**Polling frequency by priority**: +| Monitoring Type | Poll Interval | Endpoint | +|----------------|---------------|----------| +| Brand crisis monitoring | 30-60 seconds | /search?q=brand&sort=new | +| Subreddit new posts | 60-120 seconds | /r/SUB/new | +| Comment replies to own posts | 120 seconds | /message/inbox | +| Competitor mentions | 300 seconds | /search?q=competitor&sort=new | +| Weekly trend analysis | Once daily | /r/SUB/top?t=day | + +**Respect rate limits while polling**: +``` +At 30 requests/minute (app-only auth): +- 1 subreddit at 60s interval = 1 req/min → can monitor ~25 subreddits +- 1 search query at 60s interval = 1 req/min +- Reserve 5 req/min for ad-hoc queries +- Total budget: 30 req/min, plan accordingly +``` + +--- + +## Subreddit Analysis Framework + +### Evaluating a Subreddit Before Posting + +Before investing effort in any subreddit, run this assessment: + +**Step 1 — Pull subreddit metadata**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about" | python3 -c " +import sys, json +d = json.load(sys.stdin)['data'] +print(f'Subscribers: {d[\"subscribers\"]:,}') +print(f'Active now: {d[\"active_user_count\"]:,}') +print(f'Created: {d[\"created_utc\"]}') +print(f'Type: {d[\"submission_type\"]}') +print(f'Description: {d[\"public_description\"][:200]}') +" +``` + +**Step 2 — Measure actual engagement** (not just subscriber count): + +```bash +# Get top 25 hot posts and examine their scores and comment counts +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/hot?limit=25" +``` + +Calculate from the response: +``` +Engagement Score = median(post_scores) * median(num_comments) +Activity Ratio = active_user_count / subscribers +Health Indicator = (posts_per_day > 5) AND (Activity Ratio > 0.001) +``` + +**Step 3 — Subreddit quality scorecard**: + +| Factor | Good Sign | Bad Sign | +|--------|-----------|----------| +| Active/subscriber ratio | > 0.1% | < 0.01% | +| Median hot post score | > 50 | < 10 | +| Median comment count | > 10 | < 3 | +| Posts per day | 5-50 | < 1 or > 500 (noise) | +| Mod activity | Active modqueue, clear rules | No rules, spam in feed | +| Top post age | Within last 24h | Weeks old (dead subreddit) | +| Account age requirements | Reasonable (7 days) | None (spam-prone) or extreme (1 year) | + +### Peak Engagement Hours by Subreddit Type + +Optimal posting times vary by audience. All times in EST: + +| Subreddit Type | Peak Hours | Peak Days | Reasoning | +|---------------|------------|-----------|-----------| +| Tech/Programming | 9-11 AM EST | Tue-Thu | Developers browse during morning coffee | +| Business/Startup | 7-9 AM EST | Mon-Wed | Professionals check before work | +| Gaming | 6-10 PM EST | Fri-Sun | After work/school | +| Science/Academic | 10 AM-12 PM EST | Mon-Wed | Researchers between tasks | +| Lifestyle/Hobby | 12-2 PM EST, 7-9 PM EST | Any | Lunch breaks and evenings | +| News/Politics | 7-9 AM EST | Mon-Fri | Morning news cycle | +| Finance/Crypto | 8-10 AM EST | Mon-Fri | Pre-market and market open | + +To measure a specific subreddit's peak hours: +```bash +# Pull the last 100 posts and extract their timestamps +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100" +# Parse created_utc for each post and bucket by hour-of-day +# Cross-reference with score to find high-score hours, not just high-volume hours +``` + +### Competitor Presence Analysis + +**Step 1 — Search for competitor mentions**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/search?q=%22CompetitorName%22&sort=new&t=month&limit=100" +``` + +**Step 2 — Build a competitor activity profile**: +``` +For each competitor, track: +- Which subreddits they are mentioned in (and by whom -- users vs the company) +- Frequency of mentions (per week) +- Sentiment of mentions (positive / neutral / negative) +- Whether they have official accounts engaging in threads +- Common complaints about them (your opportunity) +- Common praise for them (your benchmark) +``` + +**Step 3 — Competitor comparison matrix**: +| Metric | Your Brand | Competitor A | Competitor B | +|--------|-----------|-------------|-------------| +| Weekly mentions | | | | +| Positive sentiment % | | | | +| Subreddits present in | | | | +| Official account activity | | | | +| Top complaint theme | | | | +| Top praise theme | | | | + +### Content Format Preferences by Subreddit Type + +| Subreddit Type | Preferred Format | Avoid | +|---------------|-----------------|-------| +| Technical (r/programming, r/rust) | Long-form text, code blocks, benchmarks | Short posts, images without context | +| Q&A (r/AskReddit, r/askscience) | Concise questions, detailed answers | Link-only posts | +| Showcase (r/sideproject, r/webdev) | Screenshots, demos, before/after | Text-only without visuals | +| News (r/technology, r/science) | Link to source with summary comment | Self-post opinion pieces | +| Discussion (r/startups, r/cscareerquestions) | Personal experience, specific details | Generic advice, platitudes | +| Meme-friendly (r/ProgrammerHumor) | Images, short and punchy | Long text posts | + +### Deep Subreddit Culture Analysis + +Beyond reading the sidebar, you must understand how a subreddit actually behaves. Rules are the minimum; culture is what determines success. + +**Step 1 — Analyze the top 25 hot posts for these signals:** +``` +For each post, record: +- title_length: number of words +- body_length: number of words (0 if link post) +- is_question: does title end with "?" +- has_code_block: does body contain ``` or 4-space indent +- has_external_link: does body contain URLs +- flair_used: which flair, or none +- top_comment_style: first 3 top-level comments — length, tone, use of sources +``` + +**Step 2 — Build a subreddit profile:** +``` +{ + "subreddit": "r/example", + "median_title_words": 12, + "median_body_words": 150, + "question_post_ratio": 0.4, + "code_block_frequency": 0.6, + "link_post_ratio": 0.2, + "dominant_flair": "Discussion", + "comment_style": "detailed_technical", + "avg_comment_length_words": 45, + "humor_tolerance": "low", + "self_promo_tolerance": "very_low", + "newcomer_friendliness": "moderate" +} +``` + +**Step 3 — Adapt your behavior to the profile:** + +| Profile Trait | Adaptation | +|--------------|------------| +| High `question_post_ratio` | Frame your posts as questions, even if sharing info | +| High `code_block_frequency` | Always include code examples in comments | +| Low `humor_tolerance` | No jokes, no puns, pure substance | +| Very low `self_promo_tolerance` | Never mention your own projects for at least 2 weeks of pure engagement | +| High `avg_comment_length_words` (>50) | Write detailed comments; one-liners will be ignored or downvoted | +| Low `avg_comment_length_words` (<20) | Keep it brief; walls of text will not be read | + +### Cross-Subreddit Content Adaptation Strategy + +When engaging with the same topic across multiple subreddits, each community requires a different approach. Never copy-paste. + +**Adaptation matrix example — posting about "a new Rust CLI tool":** + +| Aspect | r/rust | r/commandline | r/programming | r/sideproject | +|--------|--------|---------------|---------------|---------------| +| Title style | Technical: "crate_name: zero-copy CLI parser for X" | Practical: "crate_name -- does X in Y ms" | Neutral: "crate_name: an open-source CLI for X (Rust)" | Personal: "I built a CLI tool for X -- here's the story" | +| Body focus | Architecture, unsafe usage, benchmark vs alternatives | Install command, usage examples, screenshot | Link to repo, brief description, benchmark table | Motivation, challenges, what you learned | +| Expected length | 200-400 words + code | 100-200 words + demo gif | Link post with 2-3 sentence summary comment | 400-600 words narrative | +| Flair | "Tools & Libraries" | None typically | None | "Built This" | +| What to avoid | Marketing language, hype | Long explanations without examples | "Please star my repo" | Purely technical details without story | +| Comment engagement style | Deep technical discussion, benchmark methodology | "How does it handle edge case X?" | Brief, factual responses | Conversational, share the journey | + +**Timing stagger for multi-subreddit posts:** +- Post first in the most niche subreddit (e.g., r/rust) +- Wait 4-8 hours, observe reception +- If positive (score > 10, good comments), adapt and post to the next subreddit +- Wait another 4-8 hours between each subsequent post +- Never post to more than 3 subreddits for the same content within 48 hours + +--- + +## Growth & Reputation Building + +### Karma Building Strategies (Comment-First Approach) + +New accounts or accounts entering a new subreddit should follow the comment-first approach: + +**Week 1-2: Listen and respond** +``` +1. Sort by "new" in your target subreddits +2. Find questions you can genuinely answer +3. Write substantive, helpful comments (3+ sentences with specifics) +4. Respond to 3-5 threads per day +5. Do NOT mention your product, company, or project at all +``` + +**Week 3-4: Establish presence** +``` +1. Start sharing relevant resources (not yours) that help the community +2. Engage in discussions about trends and opinions in your domain +3. Build recognition by being consistently helpful +4. Your username should start becoming familiar to regulars +``` + +**Week 5+: Contribute original content** +``` +1. Share a technical write-up, tutorial, or analysis (unrelated to your product) +2. If well-received, you have earned the trust to occasionally mention your work +3. Always frame self-promotional content as "I built X" (transparent) not "Check out X" (spammy) +4. Maintain the 10:1 ratio — 10 helpful contributions for every 1 self-promotional post +``` + +Karma accumulation benchmarks: +| Milestone | Unlocks | +|-----------|---------| +| 10 comment karma | Bypass most anti-spam filters | +| 50 comment karma | Reduced posting cooldowns | +| 100+ comment karma in a subreddit | Trusted contributor status in some subreddits | +| 1000+ total karma | Access to r/lounge and some restricted subreddits | + +### Building Authority in Niche Subreddits + +Authority is built through consistency and expertise, not volume: + +1. **Pick 3-5 subreddits maximum** -- spreading across 20 subreddits builds no authority anywhere +2. **Develop a recognizable voice** -- consistent formatting, depth of answers, specific expertise area +3. **Answer the hard questions** -- skip the easy ones that 10 people will answer; tackle the ones that require real expertise +4. **Follow up on your own answers** -- if someone asks a follow-up, respond promptly +5. **Cite sources and show work** -- "I benchmarked this myself, here are the numbers" is worth 100x "I think X is faster" +6. **Accept corrections gracefully** -- being wrong publicly and handling it well builds more trust than never being wrong + +### Cross-Posting Etiquette and Strategy + +Cross-posting (sharing a post from one subreddit to another) has specific norms: + +**Do:** +- Use Reddit's built-in cross-post feature (preserves attribution) +- Cross-post to subreddits where the content genuinely fits +- Add a comment explaining why it is relevant to the new subreddit +- Wait at least a few hours between cross-posts (avoid appearing spammy) + +**Don't:** +- Cross-post to more than 2-3 subreddits +- Cross-post to subreddits that explicitly ban it (check rules) +- Copy-paste the same text as a new post instead of cross-posting (treated as spam) +- Cross-post your own content excessively + +**Strategic cross-posting pattern**: +``` +1. Post original content in the most specific/niche subreddit first +2. If it gains traction (>20 upvotes, positive comments), cross-post to a broader subreddit +3. Customize the title for the new audience +4. Engage in comments on BOTH subreddits +``` + +### Handling Negative Feedback and Criticism + +Negative feedback on Reddit is public and permanent. Handle it strategically: + +**Response framework**: +``` +1. PAUSE — Do not respond within the first 15 minutes. Emotional responses backfire. +2. ASSESS — Is the criticism valid, partially valid, or trolling? +3. RESPOND (or don't): + - Valid criticism: Acknowledge, thank them, explain what you will do about it + - Partially valid: Acknowledge the valid part, clarify the rest with facts + - Trolling/bad faith: Do NOT respond. Silence is the best response. +4. FOLLOW UP — If you promised to fix something, come back and confirm when it is done +``` + +**Response templates by situation**: + +| Situation | Response Pattern | +|-----------|-----------------| +| Bug report | "Thanks for reporting this. Can you share [details]? I've opened [issue link] to track it." | +| Feature complaint | "That's fair feedback. Here's why we made that choice: [reason]. We're considering [alternative]." | +| Unfair comparison | "Good question. Here's a direct comparison: [facts]. [Competitor] is great at X, we focus on Y." | +| Personal attack | Do not respond. Report if it violates rules. | +| "This is trash" | "Sorry it didn't work for you. What specifically went wrong? Happy to help." | + +--- + +## Analytics & Reporting + +### Post Performance Metrics + +Key metrics to track for every post: + +| Metric | Where to Find | What It Means | +|--------|--------------|---------------| +| Score | `data.score` | Net upvotes (upvotes minus downvotes) | +| Upvote ratio | `data.upvote_ratio` | 0.0-1.0, percentage of votes that are upvotes | +| Number of comments | `data.num_comments` | Total comments including replies | +| Awards | `data.all_awardings` | List of awards received | +| Cross-posts | `data.num_crossposts` | How many times others cross-posted it | + +**Fetch post performance**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/by_id/t3_POST_ID" +``` + +**Quality indicators**: +``` +High engagement: upvote_ratio > 0.85 AND num_comments > 20 +Controversial: upvote_ratio 0.40-0.60 (heavily split votes) +Viral potential: score > 100 within first 2 hours +Dead on arrival: score < 5 after 4 hours +Comment quality: avg comment length > 100 chars (real discussion vs memes) +``` + +### Engagement Trend Tracking + +Track performance over time by recording metrics at regular intervals: + +``` +For each post, capture at: +- T+1 hour: score, num_comments, upvote_ratio +- T+4 hours: score, num_comments, upvote_ratio +- T+24 hours: score, num_comments, upvote_ratio (final snapshot) + +For account-level tracking: +- Weekly comment karma change +- Weekly post karma change +- Number of posts/comments per subreddit +- Average score per post by subreddit +``` + +**Growth trajectory assessment**: +| Period | Healthy Growth | Stagnant | Declining | +|--------|---------------|----------|-----------| +| Weekly karma change | > +50 | -10 to +10 | < -10 | +| Avg post score trend | Increasing | Flat | Decreasing | +| Comment reply rate | > 30% of comments get replies | 10-30% | < 10% | +| New subreddit penetration | 1-2 new per month | 0 | Banned from any | + +### ROI Measurement for Business-Related Reddit Activity + +**Trackable outcomes**: +| Category | Metric | How to Track | +|----------|--------|-------------| +| Direct | Referral traffic | UTM parameters in shared links | +| Direct | Sign-ups/downloads | Reddit referral attribution | +| Direct | Support tickets deflected | Track answers that resolve issues | +| Direct | GitHub stars/forks | Append `?ref=reddit` to links | +| Indirect | Brand mention volume | Weekly search query tracking | +| Indirect | Sentiment ratio trend | Positive / total mentions over time | +| Indirect | Share of voice vs competitors | Compare mention counts monthly | + +**ROI formula**: `(Value of outcomes - Total cost) / Total cost` +where cost = (hours/week * hourly rate) + content creation time + tool costs. + +### Weekly Reddit Activity Report Template + +``` +## Reddit Activity Report — Week of [Date] +- Karma: [post] / [comment] (change: +/- [N]) | Removal rate: [N]% +- Posts: [N] (avg score: [N]) | Comments: [N] (avg score: [N]) +- Notable: [Thread title] — [subreddit] — [link] +- Plan: [Target subreddits] | [Content planned] +``` +>>>>>>> e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) diff --git a/hands/twitter/HAND.toml b/hands/twitter/HAND.toml index e0f11c0..fa74d8f 100644 --- a/hands/twitter/HAND.toml +++ b/hands/twitter/HAND.toml @@ -285,6 +285,59 @@ description = "Write tweets to a queue file for your review instead of posting d setting_type = "toggle" default = "true" +[[settings]] +key = "hashtag_strategy" +label = "Hashtag Strategy" +description = "How aggressively to use hashtags in tweets" +setting_type = "select" +default = "minimal" + +[[settings.options]] +value = "none" +label = "No hashtags" + +[[settings.options]] +value = "minimal" +label = "Minimal (0-1 per tweet)" + +[[settings.options]] +value = "moderate" +label = "Moderate (1-2 per tweet)" + +[[settings.options]] +value = "discovery" +label = "Discovery (2-3, for new accounts)" + +[[settings]] +key = "engagement_threshold" +label = "Engagement Threshold" +description = "Minimum follower count for auto-reply and auto-like targets (filters out bots and spam)" +setting_type = "select" +default = "50" + +[[settings.options]] +value = "0" +label = "No minimum" + +[[settings.options]] +value = "50" +label = "50+ followers" + +[[settings.options]] +value = "100" +label = "100+ followers" + +[[settings.options]] +value = "500" +label = "500+ followers" + +[[settings]] +key = "growth_mode" +label = "Growth Mode" +description = "Optimize strategy for growing from zero — prioritizes replies on larger accounts and community participation over original content" +setting_type = "toggle" +default = "false" + # ─── Agent configuration ───────────────────────────────────────────────────── [agent] @@ -337,19 +390,43 @@ Store strategy in knowledge graph for consistency across sessions. ## Phase 2 — Content Research & Trend Analysis -Before creating content: -1. Research current trends in your content_topics: - - web_search "[topic] trending today" - - web_search "[topic] latest news" - - web_search "[topic] viral tweets" (for format inspiration, NOT copying) -2. Check what's performing well on Twitter (via API if available): - ``` - curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \ - "https://api.twitter.com/2/tweets/search/recent?query=[topic]&max_results=10&tweet.fields=public_metrics" \ - -o trending_tweets.json - ``` -3. Identify content gaps — what's NOT being said about the topic -4. Store trending topics and insights in knowledge graph +Before creating content, run a structured trend analysis for each topic in `content_topics`: + +**Step 1 — Gather raw signals** (do all three for each topic): +- web_search "[topic] trending today" — capture headline themes +- web_search "[topic] latest news [current month year]" — recent developments +- web_search "site:twitter.com [topic] viral" — format inspiration (NOT copying) + +**Step 2 — Pull live Twitter data**: +``` +curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \ + "https://api.twitter.com/2/tweets/search/recent?query=[topic]&max_results=25&tweet.fields=public_metrics,created_at&sort_order=relevancy" \ + -o trending_tweets.json +``` + +**Step 3 — Extract actionable trends** by analyzing the gathered data: +For each topic, produce a trend brief (store in knowledge graph): +```json +{ + "topic": "AI", + "date": "2025-01-15", + "hot_narratives": ["narrative 1", "narrative 2"], + "content_gaps": ["angle nobody is covering"], + "high_engagement_formats": ["thread", "hot_take"], + "top_performing_hooks": ["example hook from trending tweet"], + "sentiment": "positive|negative|mixed", + "timeliness": "rising|peaking|declining" +} +``` +- **hot_narratives**: 2-3 themes dominating the conversation right now +- **content_gaps**: angles, counterpoints, or data nobody is surfacing yet — this is where your content wins +- **high_engagement_formats**: which tweet formats (thread, question, data) are getting the most replies in the current conversation +- **timeliness**: if "declining," skip the trend — you are too late + +**Step 4 — Prioritize**: +- Prefer trends where timeliness = "rising" and a clear content_gap exists +- Cross-reference with `hashtag_strategy` setting to decide hashtag usage +- If no strong trends exist, fall back to evergreen content from your pillars --- @@ -378,9 +455,28 @@ Tweet rules: - Stay under 280 characters (hard limit) - Front-load the hook — first line must grab attention - Use line breaks for readability -- Hashtags: 0-2 max (overuse looks spammy) +- Hashtags: follow `hashtag_strategy` setting (default: 0-2 per tweet, more looks spammy) - For threads: first tweet must stand alone as a compelling hook +Algorithm-awareness rules (maximize distribution): +- Tweets with images/video get 2-3x more impressions — include media when it adds value +- The algorithm rewards early engagement: post when your audience is online +- Tweets that earn replies within the first 30 minutes get boosted significantly +- Threads keep users on-platform (dwell time) — the algorithm favors this +- Avoid external links in the main tweet; put links in a reply instead + +Media handling: +- If the tweet references data/stats, generate a simple text summary as an image description for accessibility +- For threads with code, format code in a plain text file and reference it +- Note: Twitter API v2 media upload requires the v1.1 media/upload endpoint — use: + ``` + curl -X POST "https://upload.twitter.com/1.1/media/upload.json" \ + -H "Authorization: OAuth ..." \ + -F "media=@image.png" + ``` + Then attach the returned media_id to the tweet payload: `{"text": "...", "media": {"media_ids": ["MEDIA_ID"]}}` +- If OAuth 1.0a credentials are not configured, skip media uploads and post text-only with a note in the queue + Generate enough tweets to fill the `content_queue_size`. --- @@ -388,13 +484,49 @@ Generate enough tweets to fill the `content_queue_size`. ## Phase 4 — Content Queue & Posting If `approval_mode` is ENABLED: -1. Write generated tweets to `twitter_queue.json`: +1. Write generated tweets to `twitter_queue.json` using this schema: ```json - [{"id": "q_001", "content": "tweet text", "type": "hot_take", "created": "timestamp", "status": "pending"}] + [ + { + "id": "q_001", + "content": "tweet text here", + "thread": null, + "type": "hot_take", + "pillar": "AI", + "hashtags": ["#AI"], + "media": null, + "scheduled_for": "2025-01-15T10:00:00Z", + "created": "2025-01-14T20:00:00Z", + "status": "pending", + "trend_source": "rising narrative about LLM pricing", + "notes": "Contrarian take on open-source vs proprietary costs" + }, + { + "id": "q_002", + "content": "1/5 First tweet of thread (hook)", + "thread": ["2/5 Second tweet", "3/5 Third tweet", "4/5 Fourth", "5/5 CTA"], + "type": "thread", + "pillar": "Engineering", + "hashtags": [], + "media": null, + "scheduled_for": "2025-01-16T10:00:00Z", + "created": "2025-01-14T20:05:00Z", + "status": "pending", + "trend_source": null, + "notes": "Evergreen content on deployment patterns" + } + ] ``` + Field reference: + - `thread`: null for single tweets; array of follow-up tweet texts for threads + - `pillar`: which content pillar this serves + - `hashtags`: planned hashtags (separate from content for easy editing) + - `media`: null or `{"type": "image|video", "path": "local_path", "alt_text": "description"}` + - `trend_source`: which trend brief inspired this, or null for evergreen + - `status`: "pending" | "approved" | "rejected" | "posted" | "failed" 2. Write a human-readable `twitter_queue_preview.md` for easy review 3. event_publish "twitter_queue_updated" with queue size -4. Do NOT post — wait for user to approve via the queue file +4. Do NOT post — wait for user to approve via the queue file (user sets status to "approved") If `approval_mode` is DISABLED: 1. Post each tweet at its scheduled time via the API: @@ -425,26 +557,39 @@ During `engagement_hours`, if `auto_reply` or `auto_like` is enabled: Check mentions: ``` curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \ - "https://api.twitter.com/2/users/USER_ID/mentions?max_results=10&tweet.fields=public_metrics,created_at" \ + "https://api.twitter.com/2/users/USER_ID/mentions?max_results=20&tweet.fields=public_metrics,created_at,author_id&expansions=author_id&user.fields=public_metrics" \ -o mentions.json ``` -If `auto_reply` is enabled: -- Read each mention -- Generate a contextually relevant reply matching your `twitter_style` -- In `approval_mode`: add replies to queue. Otherwise post directly. -- NEVER argue, insult, or engage with trolls — ignore negative engagement +**Engagement decision criteria** — score each mention before acting: +- **Author follower count**: >1000 = high priority, 100-1000 = medium, <100 = low +- **Mention sentiment**: positive/neutral = engage, negative = evaluate, hostile = skip +- **Relevance to pillars**: on-topic = engage, off-topic = lower priority +- **Author engagement history**: repeat engager = always respond (loyalty signal) +- Minimum threshold from `engagement_threshold` setting: only auto-engage with mentions whose author has >= threshold followers (prevents bot noise) -If `auto_like` is enabled: +If `auto_reply` is enabled: +- Read each mention that passes the decision criteria above +- Generate a contextually relevant reply matching your `twitter_style` +- Reply priority: questions > compliments > disagreements > generic mentions +- In `approval_mode`: add replies to queue with `"type": "reply"` and `"reply_to_tweet_id"` field. Otherwise post directly. +- NEVER argue, insult, or engage with trolls — ignore negative engagement +- If a mention is hostile or toxic: do not reply, do not like. If `auto_reply` is on, log the skip reason. +- For negative but constructive feedback: reply with acknowledgment, not defensiveness +- Max replies per cycle: 15 (to stay within rate limits and avoid appearing bot-like) + +If `auto_like` is enabled (requires OAuth 1.0a credentials): ``` curl -s -X POST "https://api.twitter.com/2/users/USER_ID/likes" \ -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"tweet_id": "TWEET_ID"}' ``` -- Like tweets from people who engage with you +- Like tweets from people who engage with you (reciprocity builds community) - Like relevant content from people in your network -- Max 50 likes per cycle to avoid rate limits +- Like replies to your own tweets (encourages more replies — strong algorithm signal) +- Max 40 likes per cycle (stay well under the 50/15min rate limit) +- Skip: controversial content, political takes outside your pillars, anything you have not read --- @@ -483,6 +628,25 @@ Store insights in knowledge graph for future content optimization. --- +## Phase 8 — Growth Mode (when `growth_mode` is enabled) + +When `growth_mode` is enabled, shift strategy from broadcasting to community participation: + +1. **Reply-first approach**: Spend 70% of effort on replies to larger accounts in your niche, 30% on original content +2. **Target accounts**: Find 10-15 accounts with 5K-50K followers who post about your `content_topics` + ``` + curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \ + "https://api.twitter.com/2/tweets/search/recent?query=[topic]&max_results=25&tweet.fields=public_metrics,author_id&expansions=author_id&user.fields=public_metrics" \ + -o niche_tweets.json + ``` + Filter for authors with 5K-50K followers who get consistent replies. +3. **Reply quality**: Every reply must add value — data, counterpoint, or personal experience. Never "Great post!" or emoji-only. +4. **Original content cadence**: 1-2 tweets/day max (observations, not promotions). Save threads for week 3+. +5. **Track growth signals**: profile visits, follower growth rate, reply-to-impression ratio. If profile visits are low, your replies are not compelling enough. +6. **Disable** heavy auto-posting schedules — the algorithm penalizes low-engagement tweets, and new accounts will have low engagement. + +--- + ## Guidelines - NEVER post content that could be defamatory, discriminatory, or harmful @@ -496,6 +660,9 @@ Store insights in knowledge graph for future content optimization. - If the user messages you, pause posting and respond to their question - Monitor your API rate limit headers and back off when approaching limits - When in doubt about a tweet, DON'T post it — add it to the queue with a note +- The Twitter/X algorithm is opaque and changes without notice — track what works for YOUR account rather than relying on generic advice +- External links in tweets reduce distribution — put links in a reply to the main tweet instead +- Early engagement (first 30 min) determines reach — post when your audience is most active """ [dashboard] @@ -536,6 +703,7 @@ default_active = false [i18n.zh] name = "Twitter Hand" description = "自主 Twitter/X 管理——内容创作、定时发布、互动管理和效果追踪" +<<<<<<< HEAD category = "通信" [i18n.zh.settings.twitter_bearer_token] @@ -836,3 +1004,378 @@ description = "멘션 확인 및 소통 활동을 수행하는 시간대" [i18n.ko.settings.approval_mode] label = "승인 모드" description = "트윗을 직접 게시하지 않고 대기열 파일에 기록하여 검토" +||||||| parent of e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) +======= +category = "通信" + +[i18n.zh.settings.twitter_bearer_token] +label = "Twitter Bearer Token" +description = "Twitter/X 开发者平台的 Bearer Token,所有 Twitter API 操作均需此凭证。" + +[i18n.zh.settings.twitter_style] +label = "内容风格" +description = "推文的语气和风格" + +[i18n.zh.settings.post_frequency] +label = "发布频率" +description = "创建和发布内容的频率" + +[i18n.zh.settings.auto_reply] +label = "自动回复" +description = "自动回复提及和相关对话" + +[i18n.zh.settings.auto_like] +label = "自动点赞" +description = "自动为人脉网络中的推文和相关内容点赞" + +[i18n.zh.settings.content_topics] +label = "内容主题" +description = "要创作内容的主题(逗号分隔,例如 AI、创业、效率提升)" + +[i18n.zh.settings.brand_voice] +label = "品牌调性" +description = '描述你的独特风格(例如"用幽默简化复杂技术的创业者")' + +[i18n.zh.settings.thread_mode] +label = "推文串模式" +description = "在内容组合中加入推文串(多条推文组成的故事)" + +[i18n.zh.settings.content_queue_size] +label = "内容队列大小" +description = "待发队列中保持的推文数量" + +[i18n.zh.settings.engagement_hours] +label = "互动时段" +description = "检查提及和互动的时间段" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将推文写入队列等待审核,而非直接发布" + +[i18n.zh.settings.hashtag_strategy] +label = "话题标签策略" +description = "推文中使用话题标签的力度" + +[i18n.zh.settings.engagement_threshold] +label = "互动门槛" +description = "自动回复和点赞的最低粉丝数门槛(过滤机器人和垃圾账号)" + +[i18n.zh.settings.growth_mode] +label = "增长模式" +description = "优化从零开始的增长策略——优先在大号下评论互动,而非发布原创内容" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Twitter" +description = "Gestor autónomo de Twitter/X — creación de contenido, publicación programada, interacciones y seguimiento de rendimiento" +category = "Comunicación" + +[i18n.es.settings.twitter_bearer_token] +label = "Token Bearer de Twitter" +description = "Token Bearer del Portal de Desarrolladores de Twitter/X. Requerido para todas las operaciones de la API de Twitter." + +[i18n.es.settings.twitter_style] +label = "Estilo de contenido" +description = "Voz y tono para tus tweets" + +[i18n.es.settings.post_frequency] +label = "Frecuencia de publicación" +description = "Con qué frecuencia crear y publicar contenido" + +[i18n.es.settings.auto_reply] +label = "Respuesta automática" +description = "Responder automáticamente a menciones y conversaciones relevantes" + +[i18n.es.settings.auto_like] +label = "Me gusta automático" +description = "Dar me gusta automáticamente a tweets de tu red y contenido relevante" + +[i18n.es.settings.content_topics] +label = "Temas de contenido" +description = "Temas sobre los que crear contenido (separados por comas, ej. IA, startups, productividad)" + +[i18n.es.settings.brand_voice] +label = "Voz de marca" +description = "Describe tu voz única (ej. 'fundador sarcástico que simplifica la tecnología compleja')" + +[i18n.es.settings.thread_mode] +label = "Modo de hilos" +description = "Incluir hilos de tweets (historias de múltiples tweets) en la mezcla de contenido" + +[i18n.es.settings.content_queue_size] +label = "Tamaño de la cola de contenido" +description = "Número de tweets a mantener en la cola preparada" + +[i18n.es.settings.engagement_hours] +label = "Horario de interacción" +description = "Cuándo verificar menciones e interactuar" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Escribir los tweets en un archivo de cola para revisión en lugar de publicarlos directamente" + +[i18n.es.settings.hashtag_strategy] +label = "Estrategia de hashtags" +description = "Nivel de uso de hashtags en los tweets" + +[i18n.es.settings.engagement_threshold] +label = "Umbral de interacción" +description = "Número mínimo de seguidores para respuestas y likes automáticos (filtra bots y spam)" + +[i18n.es.settings.growth_mode] +label = "Modo de crecimiento" +description = "Optimizar la estrategia para crecer desde cero — prioriza respuestas en cuentas grandes y participación comunitaria" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "Twitter Hand" +description = "自律型Twitter/Xマネージャー——コンテンツ作成、スケジュール投稿、エンゲージメント管理、パフォーマンス追跡" +category = "コミュニケーション" + +[i18n.ja.settings.twitter_bearer_token] +label = "Twitter Bearerトークン" +description = "Twitter/X開発者ポータルのBearerトークン。すべてのTwitter API操作に必要です。" + +[i18n.ja.settings.twitter_style] +label = "コンテンツスタイル" +description = "ツイートの語調とスタイル" + +[i18n.ja.settings.post_frequency] +label = "投稿頻度" +description = "コンテンツの作成・投稿の頻度" + +[i18n.ja.settings.auto_reply] +label = "自動返信" +description = "メンションや関連する会話に自動で返信する" + +[i18n.ja.settings.auto_like] +label = "自動いいね" +description = "ネットワーク内のツイートや関連コンテンツに自動でいいねする" + +[i18n.ja.settings.content_topics] +label = "コンテンツトピック" +description = "作成するコンテンツのトピック(カンマ区切り、例: AI、スタートアップ、生産性)" + +[i18n.ja.settings.brand_voice] +label = "ブランドボイス" +description = "あなた独自の語り口を記述(例:「複雑なテクノロジーをわかりやすく伝える皮肉屋の起業家」)" + +[i18n.ja.settings.thread_mode] +label = "スレッドモード" +description = "コンテンツミックスにツイートスレッド(複数ツイートで構成するストーリー)を含める" + +[i18n.ja.settings.content_queue_size] +label = "コンテンツキューサイズ" +description = "準備キューに保持するツイートの数" + +[i18n.ja.settings.engagement_hours] +label = "エンゲージメント時間帯" +description = "メンションの確認とエンゲージメントを行う時間帯" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "ツイートを直接投稿せず、レビュー用のキューファイルに書き出す" + +[i18n.ja.settings.hashtag_strategy] +label = "ハッシュタグ戦略" +description = "ツイートでのハッシュタグの使用頻度" + +[i18n.ja.settings.engagement_threshold] +label = "エンゲージメント閾値" +description = "自動返信・自動いいねの対象となる最低フォロワー数(ボットやスパムをフィルタリング)" + +[i18n.ja.settings.growth_mode] +label = "成長モード" +description = "ゼロからの成長に最適化——大きなアカウントへのリプライとコミュニティ参加を優先し、オリジナル投稿は控えめに" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Twitter" +description = "Gestionnaire Twitter/X autonome — création de contenu, publication programmée, interactions et suivi des performances" +category = "Communication" + +[i18n.fr.settings.twitter_bearer_token] +label = "Jeton Bearer Twitter" +description = "Jeton Bearer du Portail Développeurs Twitter/X. Requis pour toutes les opérations de l'API Twitter." + +[i18n.fr.settings.twitter_style] +label = "Style de contenu" +description = "Ton et style pour vos tweets" + +[i18n.fr.settings.post_frequency] +label = "Fréquence de publication" +description = "Fréquence de création et de publication de contenu" + +[i18n.fr.settings.auto_reply] +label = "Réponse automatique" +description = "Répondre automatiquement aux mentions et conversations pertinentes" + +[i18n.fr.settings.auto_like] +label = "Like automatique" +description = "Aimer automatiquement les tweets de votre réseau et le contenu pertinent" + +[i18n.fr.settings.content_topics] +label = "Sujets de contenu" +description = "Sujets sur lesquels créer du contenu (séparés par des virgules, ex. IA, startups, productivité)" + +[i18n.fr.settings.brand_voice] +label = "Voix de marque" +description = "Décrivez votre voix unique (ex. 'fondateur sarcastique qui simplifie la technologie complexe')" + +[i18n.fr.settings.thread_mode] +label = "Mode fil de discussion" +description = "Inclure des fils de tweets (histoires à plusieurs tweets) dans le mix de contenu" + +[i18n.fr.settings.content_queue_size] +label = "Taille de la file de contenu" +description = "Nombre de tweets à maintenir dans la file d'attente préparée" + +[i18n.fr.settings.engagement_hours] +label = "Heures d'engagement" +description = "Quand vérifier les mentions et interagir" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Écrire les tweets dans un fichier d'attente pour révision au lieu de les publier directement" + +[i18n.fr.settings.hashtag_strategy] +label = "Stratégie de hashtags" +description = "Niveau d'utilisation des hashtags dans les tweets" + +[i18n.fr.settings.engagement_threshold] +label = "Seuil d'engagement" +description = "Nombre minimum d'abonnés pour les réponses et likes automatiques (filtre les bots et le spam)" + +[i18n.fr.settings.growth_mode] +label = "Mode croissance" +description = "Optimiser la stratégie pour une croissance depuis zéro — privilégie les réponses aux grands comptes et la participation communautaire" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Twitter-Hand" +description = "Autonomer Twitter/X-Manager — Content-Erstellung, geplante Veröffentlichung, Engagement-Management und Performance-Tracking" +category = "Kommunikation" + +[i18n.de.settings.twitter_bearer_token] +label = "Twitter Bearer-Token" +description = "Bearer-Token vom Twitter/X-Entwicklerportal. Erforderlich für alle Twitter-API-Operationen." + +[i18n.de.settings.twitter_style] +label = "Inhaltsstil" +description = "Ton und Stil für Ihre Tweets" + +[i18n.de.settings.post_frequency] +label = "Veröffentlichungshäufigkeit" +description = "Wie oft Inhalte erstellt und veröffentlicht werden" + +[i18n.de.settings.auto_reply] +label = "Automatische Antwort" +description = "Automatisch auf Erwähnungen und relevante Gespräche antworten" + +[i18n.de.settings.auto_like] +label = "Automatisches Like" +description = "Tweets im Netzwerk und relevante Inhalte automatisch liken" + +[i18n.de.settings.content_topics] +label = "Inhaltsthemen" +description = "Themen für die Content-Erstellung (kommagetrennt, z.B. KI, Startups, Produktivität)" + +[i18n.de.settings.brand_voice] +label = "Markenstimme" +description = "Beschreiben Sie Ihre einzigartige Stimme (z.B. 'sarkastischer Gründer, der komplexe Technologie vereinfacht')" + +[i18n.de.settings.thread_mode] +label = "Thread-Modus" +description = "Tweet-Threads (mehrteilige Tweet-Geschichten) in den Content-Mix aufnehmen" + +[i18n.de.settings.content_queue_size] +label = "Größe der Content-Warteschlange" +description = "Anzahl der Tweets in der vorbereiteten Warteschlange" + +[i18n.de.settings.engagement_hours] +label = "Engagement-Zeiten" +description = "Wann Erwähnungen geprüft und interagiert werden soll" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Tweets in eine Warteschlangendatei zur Überprüfung schreiben, anstatt sie direkt zu veröffentlichen" + +[i18n.de.settings.hashtag_strategy] +label = "Hashtag-Strategie" +description = "Intensität der Hashtag-Nutzung in Tweets" + +[i18n.de.settings.engagement_threshold] +label = "Engagement-Schwelle" +description = "Mindestanzahl an Followern für automatische Antworten und Likes (filtert Bots und Spam)" + +[i18n.de.settings.growth_mode] +label = "Wachstumsmodus" +description = "Strategie für Wachstum von null optimieren — priorisiert Antworten bei größeren Accounts und Community-Beteiligung" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "Twitter Hand" +description = "자율 Twitter/X 관리 — 콘텐츠 제작, 예약 게시, 소통 관리 및 성과 추적" +category = "커뮤니케이션" + +[i18n.ko.settings.twitter_bearer_token] +label = "Twitter Bearer 토큰" +description = "Twitter/X 개발자 포털의 Bearer 토큰. 모든 Twitter API 작업에 필수." + +[i18n.ko.settings.twitter_style] +label = "콘텐츠 스타일" +description = "트윗의 어조와 스타일" + +[i18n.ko.settings.post_frequency] +label = "게시 빈도" +description = "콘텐츠를 작성하고 게시하는 주기" + +[i18n.ko.settings.auto_reply] +label = "자동 답글" +description = "멘션 및 관련 대화에 자동으로 답글 작성" + +[i18n.ko.settings.auto_like] +label = "자동 좋아요" +description = "네트워크 내 트윗 및 관련 콘텐츠에 자동으로 좋아요" + +[i18n.ko.settings.content_topics] +label = "콘텐츠 주제" +description = "콘텐츠를 작성할 주제 (쉼표로 구분, 예: AI, 스타트업, 생산성)" + +[i18n.ko.settings.brand_voice] +label = "브랜드 보이스" +description = "고유한 스타일을 설명 (예: '복잡한 기술을 쉽게 풀어내는 유머러스한 창업자')" + +[i18n.ko.settings.thread_mode] +label = "스레드 모드" +description = "콘텐츠 구성에 트윗 스레드 (다중 트윗 스토리) 포함" + +[i18n.ko.settings.content_queue_size] +label = "콘텐츠 대기열 크기" +description = "준비 대기열에 유지할 트윗 수" + +[i18n.ko.settings.engagement_hours] +label = "소통 시간대" +description = "멘션 확인 및 소통 활동을 수행하는 시간대" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "트윗을 직접 게시하지 않고 대기열 파일에 기록하여 검토" + +[i18n.ko.settings.hashtag_strategy] +label = "해시태그 전략" +description = "트윗에서 해시태그를 사용하는 정도" + +[i18n.ko.settings.engagement_threshold] +label = "소통 기준" +description = "자동 답글 및 좋아요 대상의 최소 팔로워 수 (봇과 스팸 필터링)" + +[i18n.ko.settings.growth_mode] +label = "성장 모드" +description = "제로에서 시작하는 성장 전략 최적화 — 대형 계정에 답글과 커뮤니티 참여를 우선시" +>>>>>>> e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) diff --git a/hands/twitter/SKILL.md b/hands/twitter/SKILL.md index 9278bae..330772a 100644 --- a/hands/twitter/SKILL.md +++ b/hands/twitter/SKILL.md @@ -105,6 +105,78 @@ Always check response headers: --- +## Algorithm Optimization + +The following signals are known to affect distribution as of 2024-2025. Treat as heuristics -- validate against your own account's data. + +### Signals That Boost Distribution +| Signal | Why It Matters | How to Leverage | +|--------|---------------|-----------------| +| Early engagement (first 30 min) | Algorithm tests tweets on a small audience first; high early engagement triggers wider distribution | Post when your audience is most active; craft strong hooks | +| Dwell time | Time spent reading your tweet/thread counts as engagement | Write threads (keeps users scrolling), use line breaks for readability | +| Replies (especially conversations) | Reply chains signal valuable content | End tweets with questions; reply to your own replies to keep threads going | +| Bookmarks/saves | Strong quality signal (user wants to return) | Post actionable content (how-tos, frameworks, checklists) worth saving | +| Profile visits after viewing | Indicates your content made someone curious about you | Ensure your bio clearly states your expertise and value prop | + +### Signals That Suppress Distribution +| Signal | Impact | Avoidance | +|--------|--------|-----------| +| External links in tweet body | Reduced impressions (Twitter wants users on-platform) | Post the content natively; put links in a reply | +| Hashtag spam (3+) | Triggers spam filters | Use 0-2 relevant hashtags maximum | +| Rapid-fire posting | Floods follower timelines, reduces per-tweet engagement | Space posts 2-3 hours apart minimum | +| Low engagement ratio | Tweets with many impressions but no interaction signal low quality | Delete or don't repeat content formats that consistently underperform | +| Engagement bait without substance | "Like if you agree" without actual content | Pair CTAs with genuine value | + +### Algorithm-Aware Posting Strategy +1. **Test before committing**: Post a single tweet on a topic. If engagement is above-average in 1 hour, follow up with a thread within 24 hours. +2. **Reply to yourself**: Add a reply with a link or context. This creates a conversation thread that boosts the original. +3. **Engagement window**: Reply to comments on your tweets within the first hour. Reply chains are rewarded. +4. **Content recycling**: A tweet that performed well 3+ months ago can be reposted with fresh wording. + +--- + +## Media Upload Handling + +### Twitter API v2 Media Upload +Twitter API v2 has no media upload endpoint. Use the v1.1 endpoint, which requires OAuth 1.0a. + +**Simple upload (images < 5MB, GIFs < 15MB)**: +```bash +curl -X POST "https://upload.twitter.com/1.1/media/upload.json" \ + -H "Authorization: OAuth oauth_consumer_key=...,oauth_token=...,oauth_signature=..." \ + -F "media=@/path/to/image.png" +``` +Response: `{"media_id": 123456789, "media_id_string": "123456789"}` + +**Attach media to a tweet**: +```bash +curl -s -X POST "https://api.twitter.com/2/tweets" \ + -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"text": "Check this out", "media": {"media_ids": ["123456789"]}}' +``` + +**Alt text for accessibility** (set after upload, before tweeting): +```bash +curl -X POST "https://upload.twitter.com/1.1/media/metadata/create.json" \ + -H "Authorization: OAuth ..." \ + -H "Content-Type: application/json" \ + -d '{"media_id": "123456789", "alt_text": {"text": "Description of the image"}}' +``` + +### When to Use Media +- **Data/stats tweets**: Chart or highlighted number as image -- 2-3x more impressions +- **Thread hooks**: Image in tweet 1 increases click-through +- **Code snippets**: Screenshot with syntax highlighting beats plain text +- **Before/after**: Visual comparisons are highly shareable + +### When to Skip Media +- OAuth 1.0a credentials not configured (Bearer Token alone cannot upload) +- Image does not add information beyond the text +- Attaching media would delay posting past the optimal window + +--- + ## Content Strategy Framework ### Content Pillars @@ -226,6 +298,7 @@ Do NOT auto-like: --- +<<<<<<< HEAD ## Advanced Engagement Patterns ### Quote Tweet vs Reply vs Retweet @@ -292,6 +365,104 @@ A thread that performed well contains 5-7 standalone content pieces. Extract the --- +||||||| parent of e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) +======= +## Advanced Engagement Patterns + +### Quote Tweet vs Reply vs Retweet + +Choosing the right interaction type determines whether you gain visibility or waste it. + +**Use a Quote Tweet when**: +- You have a distinct take or added context (not just "this!") +- The original tweet has high impressions and you want to draft off its reach +- You are crediting someone while adding your own insight for your audience +- The original author has a similar or larger following (exposes you to their audience) + +**Use a Reply when**: +- You want to build a direct relationship with the author +- Your comment only makes sense in context of the original +- The original author has a much larger following (replies show on their thread, giving you visibility without looking self-promotional) +- You are answering a question or adding a correction + +**Use a plain Retweet when**: +- The original says everything perfectly and you have nothing to add +- You want to signal-boost a community member, customer, or partner +- The content is time-sensitive (breaking news, event announcements) + +**Avoid**: +- Quote tweeting with only emojis or "this" -- adds no value, looks lazy +- Quote tweeting someone with fewer followers just to dunk -- punching down +- Retweeting more than 3-4 times per day -- dilutes your original content ratio + +### Thread Repurposing + +A thread that performed well contains 5-7 standalone content pieces. Extract them over the following week to maximize ROI. + +**Process**: +1. Day 0 (original): Post the full thread +2. Day 2: Pull the single most quotable tweet from the thread. Post it standalone with slightly different wording. No link back to the thread +3. Day 4: Turn a data point or example from the thread into a graphic or screenshot tweet +4. Day 6: Post the thread's core thesis as a hot take (one tweet, punchy) +5. Day 8+: If engagement stayed strong, post a "Part 2" thread that goes deeper on whichever tweet in the original got the most replies + +**Rules**: +- Change the wording each time -- copy-pasting feels like spam to followers who saw the original +- Space extractions at least 48 hours apart +- Stop if any extraction underperforms significantly -- the topic is tapped out +- Never repurpose a thread that got low engagement; the content did not resonate + +### Trending Topic Participation + +**When to participate**: +- The trend directly intersects one of your content pillars +- You have a genuine, informed perspective (not a generic reaction) +- The trend is still rising (check the "Trending" tab; if it has been trending for >12 hours, you are late) +- The tone of the trend matches your brand voice + +**When to avoid**: +- Tragedy, disaster, or crisis events -- opportunistic posting destroys trust +- Highly polarized political or social debates outside your expertise +- Trends driven by outrage mobs -- associating your brand is high-risk, low-reward +- You would need to force-fit your product or message into the trend + +**Execution**: +- Lead with your actual insight, not the hashtag. The hashtag goes at the end or is omitted entirely if the topic keyword is in your text +- Be early or be different. If 50 people have already made the same joke, skip it +- Tie back to your pillar: "Trend X is exactly why [your pillar topic] matters more than ever" + +--- + +## Crisis & Negative Comment Management + +### Classifying Negative Interactions + +Not all negative replies require the same response. Classify before acting: + +| Type | Example | Action | +|------|---------|--------| +| **Constructive criticism** | "Your benchmark methodology is flawed because X" | Reply with acknowledgment, address the specific point, thank them | +| **Frustrated user** | "I tried your tool and it broke on my setup" | Reply publicly with empathy, ask for details, move to DMs if needed | +| **Trolling** | Personal insults, bad-faith arguments, bait | Do not reply. Block if repeated. Never quote-tweet to "expose" them | +| **Misinformation about you** | Factually wrong claims about your product/work | Reply once with facts and evidence. Do not engage further if they persist | +| **Pile-on / ratio** | Many negative replies at once, often from outside your audience | Pause all posting. Do not delete the original tweet (looks like hiding). Wait 24 hours before responding | + +### Response Templates +- **Constructive criticism**: "Fair point — [acknowledgment]. We actually [explanation]. Appreciate you raising this." +- **Frustrated user**: "Sorry you hit that. Can you share [detail]? Happy to help sort it out." +- **Factual correction**: "To clarify — [correct info with source]. Happy to discuss further." + +### Rules During a Crisis +1. **Stop all scheduled posts immediately** — auto-posting during a crisis looks tone-deaf +2. **Do not delete** the original tweet unless it contains genuinely harmful misinformation +3. **Acknowledge** the situation in a single, clear tweet if it involves your product/brand +4. **Do not be defensive** — own mistakes directly +5. **Wait before responding** — draft a response and review it after 1 hour +6. **Resume normal posting** only after the situation has cooled down (24-48 hours minimum) + +--- + +>>>>>>> e65ad25 (feat(hands): improve linkedin, reddit, and twitter hands) ## Content Calendar Template ```