# Forum Marketing

> Forum Marketing — Grassroots Traffic, Trust & Style Matching

- Skill: `lucadominguez/forum-marketing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add lucadominguez/forum-marketing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lucadominguez/forum-marketing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Marketing & Growth
- Author: lucadominguez (https://skillmd.com/u/lucadominguez)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/lucadominguez/forum-marketing

---

# Forum Marketing — Grassroots Traffic, Trust & Style Matching

Complete forum marketing orchestration with advanced linguistic style matching.
Integrates open-source tools with existing Hermes skills for an end-to-end
pipeline: corpus extraction → style analysis → persona calibration → content
generation in forum-native voice → multi-account deployment → anti-detection.

## Philosophy

Effective forum marketing doesn't look like marketing. It looks like a genuine
community member sharing something they found valuable. The key insight: **you
must write exactly like the community writes.** Not "good writing" — THEIR writing.
Same sentence rhythms, same jargon, same humor register, same formatting quirks.
When your post is indistinguishable from a top-voted community post, you win.

Three principles:

1. **Style match before you post.** Scrape the forum's top content. Extract
   linguistic patterns. Generate only after you understand how they talk.
2. **Give before you take.** 80% of posts should be genuine contributions with
   zero promotion. Build the account's reputation first.
3. **The thread is the product.** A well-crafted discussion with stylistically
   matched comments is worth more than any link drop.

## When to Use

- User wants to promote a product, SaaS, tool, website, or content via forums
- User asks about "forum marketing," "Reddit promotion," "grassroots campaigns"
- User wants posts that match a specific forum's writing style
- User says "write like they do" or "match the style of r/..."
- User wants to orchestrate multi-account engagement on a thread
- User needs to build trust/credibility in a forum before promoting

**Don't use for:**
- Single-platform social media (use x-posting-agent)
- Pure content marketing without forum engagement
- One-off link drops without style analysis (waste of effort)

## Tool Ecosystem: What We Have vs. What's Open Source

This skill bridges existing Hermes skills with external open-source tools:

| Pipeline Stage | Hermes Skill | External Open-Source Tool |
|---|---|---|
| Forum Discovery | `agent-reach` (Exa search, Jina Reader) | PRAW subreddit search, subredditstats.com |
| Corpus Extraction | `agent-reach` (page reading) | PRAW, asyncpraw, arctic-shift (historical data) |
| Linguistic Style Analysis | `voice-humanizer` (voice fingerprint) | textstat, NLTK, spaCy, stylo (R), jstylometry |
| AI Tell Removal | `humanizer` (28-pattern detection) | brandonwise/humanizer CLI, GPTZero API |
| Narrative Alignment | `narrative-mimicry` (community narratives) | PRAW top-posts corpus analysis |
| Content Generation | DeepSeek V4 Pro (LLM drafting) | LLaMA/Mistral local models for batch generation |
| Browser Automation | `browser-automation` (Playwright, stealth) | puppeteer-extra-plugin-stealth, playwright-stealth, undetected-chromedriver |
| Proxy Management | `browser-automation` (ProxyEmpire) | proxybroker, proxy-pool, BrightData, IPRoyal |
| Multi-Account Mgmt | - | Playwright contexts, Multilogin (reference), session-storage isolation |
| API Posting | - | PRAW (Python), snoowrap (JS), asyncpraw (async) |
| Scheduling | `x-posting-agent` patterns | cronjob, custom Python scheduler |
| Analytics | - | PRAW post metrics, SocialGrep, reddit-trends, custom analytics |
| Anti-Detection | `browser-automation` (full coverage) | puppeteer-extra-stealth, fingerprint-suite, camo-proxy |

## Architecture

```
~/.hermes/forum-marketing/
├── campaigns.json                    — active and archived campaigns
├── accounts.json                     — forum account registry (personas)
├── forums.json                       — discovered forums with metadata
├── proxies.json                      — proxy pool assignments
├── <campaign-id>/
│   ├── campaign.json                 — campaign parameters + status
│   ├── forum_corpus/                 — PHASE 0: scraped forum content
│   │   ├── <forum>-top-posts.json    — top 50-100 posts
│   │   ├── <forum>-top-comments.json — top comments
│   │   └── <forum>-corpus.txt       — plaintext for NLP
│   ├── style_analysis/               — PHASE 0: linguistic analysis
│   │   ├── <forum>-fingerprint.json  — stylometric fingerprint
│   │   ├── <forum>-vocab-frequency.csv
│   │   └── <forum>-style-rules.md    — human-readable style guide
│   ├── persona_calibration/          — PHASE 1: persona tuning
│   │   └── <persona>-voice.json      — calibrated voice per persona
│   ├── op_drafts/                    — PHASE 2: OP drafts
│   │   └── <date>-<version>.md
│   ├── comment_drafts/               — PHASE 3: staged comments
│   │   └── <persona>-<sequence>.md
│   ├── schedule.json                 — timing plan
│   ├── published.json               — published post/comment IDs + URLs
│   └── metrics.json                 — engagement + traffic data
└── templates/
    ├── persona_template.json
    ├── style_extraction.py           — corpus extraction script
    └── style_analyzer.py             — stylometric analysis script
```

## Phase 0: Linguistic Style Analysis (RUN FIRST — NEVER SKIP)

This is the most important phase. Posts that don't match the forum's writing
style get downvoted, flagged, or banned. Posts that match become top content.

### 0.1 — Corpus Extraction

Extract 50-100 top posts + their top comments from the target forum:

**Reddit via PRAW (Python Reddit API Wrapper):**

```python
# Install: pip install praw
# Setup: Reddit API credentials at https://www.reddit.com/prefs/apps

import praw
import json
from datetime import datetime

reddit = praw.Reddit(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    user_agent="forum-style-analyzer/1.0"
)

subreddit = reddit.subreddit("TARGET_SUBREDDIT")

corpus = []
# Top posts from past year
for post in subreddit.top(time_filter="year", limit=100):
    entry = {
        "id": post.id,
        "title": post.title,
        "selftext": post.selftext,
        "score": post.score,
        "num_comments": post.num_comments,
        "upvote_ratio": post.upvote_ratio,
        "created_utc": post.created_utc,
        "author": str(post.author) if post.author else "[deleted]",
        "flair": post.link_flair_text,
        "url": post.url,
        "top_comments": []
    }
    # Extract top 5 comments per post
    post.comments.replace_more(limit=0)
    for comment in post.comments[:5]:
        entry["top_comments"].append({
            "id": comment.id,
            "body": comment.body,
            "score": comment.score,
            "author": str(comment.author) if comment.author else "[deleted]",
        })
    corpus.append(entry)

# Save
with open("forum_corpus/<forum>-top-posts.json", "w") as f:
    json.dump(corpus, f, indent=2)
```

**Alternative: asyncpraw for bulk extraction (faster):**

```bash
pip install asyncpraw
```

```python
import asyncio
import asyncpraw

async def extract_corpus(subreddit_name, limit=100):
    reddit = asyncpraw.Reddit(
        client_id="...",
        client_secret="...",
        user_agent="forum-style-analyzer/1.0"
    )
    subreddit = await reddit.subreddit(subreddit_name)
    posts = []
    async for post in subreddit.top(time_filter="year", limit=limit):
        posts.append(post)
    return posts
```

**Non-Reddit forums:**

```bash
# Use agent-reach's Jina Reader for forum scraping
curl -s "https://r.jina.ai/FORUM_URL" > forum_page.md

# For Discourse forums, use their JSON API
curl -s "https://FORUM_URL/latest.json" | python3 -m json.tool

# For XenForo/phpBB, use agent-reach + manual page extraction
```

**Historical data via arctic-shift (Reddit):**

```bash
# arctic-shift is the Pushshift successor — free Reddit search API
curl -s "https://arctic-shift.photon-reddit.com/api/posts/search?subreddit=SUBREDDIT&sort=top&limit=50"
```

### 0.2 — Linguistic Fingerprint Extraction

Extract the forum's writing style fingerprint using textstat + NLTK/spaCy:

```python
# Install: pip install textstat nltk spacy
# python -m spacy download en_core_web_sm

import textstat
import nltk
import json
from collections import Counter
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk.corpus import stopwords

nltk.download('punkt')
nltk.download('stopwords')
nltk.download('averaged_perceptron_tagger')

def extract_forum_fingerprint(corpus_file):
    """Extract comprehensive linguistic fingerprint from forum corpus."""
    with open(corpus_file) as f:
        posts = json.load(f)

    all_text = []
    all_titles = []
    all_comments = []

    for post in posts:
        all_titles.append(post["title"])
        if post["selftext"]:
            all_text.append(post["selftext"])
        for comment in post.get("top_comments", []):
            all_comments.append(comment["body"])

    full_corpus = " ".join(all_text + all_comments)
    sentences = sent_tokenize(full_corpus)
    words = word_tokenize(full_corpus.lower())
    words_no_stop = [w for w in words if w not in stopwords.words('english') and w.isalpha()]

    fingerprint = {
        "forum_id": "<forum-slug>",
        "analyzed_at": datetime.utcnow().isoformat(),
        "corpus_stats": {
            "total_posts": len(posts),
            "total_comments": len(all_comments),
            "total_words": len(words),
            "total_sentences": len(sentences),
            "avg_post_length_chars": sum(len(t) for t in all_text) / max(len(all_text), 1),
            "avg_comment_length_chars": sum(len(c) for c in all_comments) / max(len(all_comments), 1),
        },
        "readability": {
            "flesch_reading_ease": textstat.flesch_reading_ease(full_corpus),
            "flesch_kincaid_grade": textstat.flesch_kincaid_grade(full_corpus),
            "gunning_fog": textstat.gunning_fog(full_corpus),
            "smog_index": textstat.smog_index(full_corpus),
            "automated_readability_index": textstat.automated_readability_index(full_corpus),
        },
        "sentence_structure": {
            "avg_sentence_length_words": len(words) / max(len(sentences), 1),
            "sentence_length_distribution": _get_length_distribution(sentences),
            "avg_sentences_per_paragraph": _avg_sentences_per_paragraph(all_text),
        },
        "vocabulary": {
            "top_words": [w for w, c in Counter(words_no_stop).most_common(100)],
            "top_bigrams": [f"{a}_{b}" for a, b, c in Counter(
                zip(words_no_stop, words_no_stop[1:])
            ).most_common(50)],
            "unique_word_ratio": len(set(words_no_stop)) / max(len(words_no_stop), 1),
        },
        "parts_of_speech": _pos_distribution(full_corpus),
        "punctuation": {
            "exclamation_per_sentence": full_corpus.count('!') / max(len(sentences), 1),
            "question_per_sentence": full_corpus.count('?') / max(len(sentences), 1),
            "parentheses_per_sentence": (full_corpus.count('(') + full_corpus.count(')')) / max(len(sentences), 1),
            "em_dash_count": full_corpus.count('—') + full_corpus.count('–'),
        },
        "formatting_conventions": {
            "bold_usage": _count_markdown_pattern(full_corpus, r'\*\*.*?\*\*'),
            "italic_usage": _count_markdown_pattern(full_corpus, r'\*.*?\*'),
            "code_block_usage": _count_markdown_pattern(full_corpus, r'`.*?`'),
            "bullet_list_usage": sum(1 for line in full_corpus.split('\n') if line.strip().startswith(('- ', '* ', '1. '))),
            "quote_block_usage": sum(1 for line in full_corpus.split('\n') if line.startswith('>')),
        },
        "tone_indicators": {
            "swear_word_ratio": _count_swear_words(words) / max(len(words), 1),
            "hedging_ratio": _count_hedging(words) / max(len(words), 1),
            "first_person_ratio": words.count('i') / max(len(words), 1),
            "second_person_ratio": words.count('you') / max(len(words), 1),
            "contraction_ratio": _count_contractions(full_corpus) / max(len(words), 1),
        },
        "formatting_markers": _extract_formatting_markers(all_text + all_comments),
    }

    return fingerprint
```

### 0.3 — Style Rules Generation

From the fingerprint, generate a human-readable style guide for the forum:

```markdown
## r/SUBREDDIT Style Rules (auto-generated)

### Readability Target
- Flesch-Kincaid Grade: 7.2 → Write at ~7th grade level
- Average sentence: 16 words
- Average post: 340 characters
- Average comment: 85 characters

### Sentence Rhythm
- Mix of short (4-8 words) and medium (12-20 words)
- Avoid long sentences (>30 words) — they don't exist here
- Fragments are common and accepted

### Vocabulary
- Top words: [extracted]
- Jargon specific to this community: [extracted]
- Avoid: formal/academic vocabulary, corporate speak

### Formatting
- Bold: rare, for emphasis only
- Bullet lists: common in top posts
- Code blocks: frequent (technical community)
- No emoji (or minimal)

### Tone
- Direct, slightly irreverent
- First-person is standard
- Swearing: occasional, matches community
- Humor: deadpan/self-deprecating
- Hedging: low — this community states opinions directly

### Openings & Closings
- Common openings: "Honestly...", "Hot take:", "PSA:"
- Common closings: questions, TL;DRs, "Edit:" follow-ups
```

### 0.4 — Advanced Stylometric Analysis (for maximum match)

For deeper matching, use the `voice-humanizer` skill's fingerprinting system:

```
Load: voice-humanizer

Run the stylometric extraction prompt on the forum corpus as if it were
a "voice sample." This gives you the 12-dimension voice fingerprint
(sentence length, rhythm, openings, closings, function words, punctuation,
register, contractions, hedging, idioms, paragraph rhythm, do/don't rules).

Save this as ~/.hermes/forum-marketing/<campaign>/style_analysis/<forum>-voice-fingerprint.json
```

Then use the `narrative-mimicry` skill to detect community narratives:

```
Load: narrative-mimicry

Run Phase 1 (Narrative Detection) on the forum corpus to identify:
- Dominant narratives (>15% frequency)
- Established narratives (5-15%)
- Counter-narratives
- Sacred concepts and forbidden moves

Save to ~/.hermes/forum-marketing/<campaign>/style_analysis/<forum>-narratives.json
```

**Combined output:** You now have:
1. **Linguistic fingerprint** — HOW they write (syntax, vocabulary, rhythm)
2. **Voice fingerprint** — finer-grained voice traits (from voice-humanizer)
3. **Narrative map** — WHAT they believe and argue about (from narrative-mimicry)

This triad is the foundation. Every post you generate passes through all three filters.

### 0.5 — Style Verification (Pre-Post Check)

Before posting anything, run the draft through the style matcher:

```python
def verify_style_match(draft_text, forum_fingerprint):
    """Score how well a draft matches the forum's style."""
    draft_sentences = sent_tokenize(draft_text)
    draft_words = word_tokenize(draft_text.lower())
    forum_sent_len = forum_fingerprint["sentence_structure"]["avg_sentence_length_words"]
    forum_grade = forum_fingerprint["readability"]["flesch_kincaid_grade"]

    scores = {
        "readability_diff": abs(textstat.flesch_kincaid_grade(draft_text) - forum_grade),
        "sentence_length_diff": abs(
            len(draft_words) / max(len(draft_sentences), 1) - forum_sent_len
        ),
        "vocab_overlap": len(
            set(draft_words) & set(forum_fingerprint["vocabulary"]["top_words"])
        ) / max(len(set(draft_words)), 1),
    }

    # Thresholds
    issues = []
    if scores["readability_diff"] > 2:
        issues.append(f"Readability off by {scores['readability_diff']:.1f} grades")
    if scores["sentence_length_diff"] > 8:
        issues.append("Sentence length doesn't match forum rhythm")

    return {
        "pass": len(issues) == 0,
        "scores": scores,
        "issues": issues,
    }
```

**Gate rule:** If style verification returns `pass: false`, rewrite the draft
before posting. Never post style-mismatched content.

## Phase 1: Forum Discovery

### 1.1 — Identify Target Forums

Find 5-15 candidate forums using multiple discovery methods:

**Method A: PRAW subreddit discovery**

```python
import praw

reddit = praw.Reddit(...)

# Search for subreddits by keyword
for sub in reddit.subreddits.search("NICHE_KEYWORD", limit=20):
    print(f"r/{sub.display_name}: {sub.subscribers:,} subscribers — {sub.public_description[:100]}")

# Find related subreddits
target = reddit.subreddit("KNOWN_SUBREDDIT")
# Check sidebar/wiki for related communities
# Check crossposted content for source subreddits
```

**Method B: arctic-shift community search**

```bash
# Search for subreddits that discuss your topic
curl -s "https://arctic-shift.photon-reddit.com/api/posts/search?query=KEYWORD&sort=top&limit=20" \
  | python3 -c "import json,sys; data=json.load(sys.stdin); [print(p['subreddit']) for p in data['data']]" \
  | sort | uniq -c | sort -rn
```

**Method C: Exa semantic search (agent-reach)**

```bash
export PATH="$HOME/.hermes/node/bin:$PATH"
mcporter call 'exa.web_search_exa(query: "site:reddit.com best subreddits for [NICHE] discussion community", numResults: 10)'
```

**Method D: Niche forum discovery**

```bash
mcporter call 'exa.web_search_exa(query: "[NICHE] forum community discussion site:discourse OR site:xenforo OR site:phpbb", numResults: 10)'
```

### 1.2 — Score and Select

Score each forum on:

| Factor | Weight | How to Measure |
|--------|--------|---------------|
| Audience relevance | 5 | Manual assessment |
| Traffic potential | 4 | PRAW `.subscribers`, monthly active users |
| Link tolerance | 4 | Read subreddit rules; check if link posts allowed |
| Moderation climate | 3 | Check moderator activity, ban patterns |
| Account age gate | 3 | Test post with warm account; note removals |
| Style match difficulty | 3 | Phase 0 analysis — how homogeneous is the style? |
| SEO value | 2 | Google "site:reddit.com/r/SUBREDDIT KEYWORD" |
| Competitor presence | 2 | PRAW search for competitor mentions |

Select top 3-5 forums. More than 5 is unmanageable.

### 1.3 — Forum Deep Dive

For each selected forum, run the full Phase 0 analysis. Document:
- Self-promotion policy
- Link posting rules
- Account age/karma minimums
- Content format rules
- Banned topics or domains
- Moderator pet peeves
- **Style fingerprint** (from Phase 0.2)
- **Style rules** (from Phase 0.3)
- **Narrative map** (from Phase 0.4)

## Phase 2: Persona Creation & Voice Calibration

### 2.1 — Persona Design with Forum-Native Voice

Each persona must write like a natural member of the target forum. Use the
forum's style fingerprint as the baseline, then add individual variation:

**Process:**

1. Load the forum's linguistic fingerprint (Phase 0.2)
2. Load the forum's voice fingerprint (Phase 0.4 via voice-humanizer)
3. Generate 3-5 persona variations that all match the forum fingerprint
   but differ subtly from each other
4. Calibrate each persona's voice using the voice-humanizer's do/don't rules

**Persona variation dimensions (keep these distinct per persona):**
- Sentence length: ±3 words from forum average
- Technical depth: beginner / intermediate / expert
- Humor: deadpan / enthusiastic / none
- Hedging: low (confident) / medium (nuanced)
- Contrarianism: mainstream / slightly contrarian / skeptical

```json
{
  "persona_id": "rust-dev-73",
  "platform": "reddit",
  "username": "rust_dev_73",
  "forum_profile": "r/rust",
  "forum_fingerprint_ref": "r-rust-fingerprint.json",
  "persona_description": "Mid-career systems programmer, writes C++ at work but Rust for side projects. Knows the language deeply but not an influencer. Answers newbie questions patiently, gets technical in advanced threads. Occasionally frustrated with async Rust.",
  "voice_calibration": {
    "baseline": "r/rust forum fingerprint",
    "variations": {
      "sentence_length": "-2 words from forum avg",
      "technical_depth": "expert (uses jargon naturally)",
      "humor": "deadpan, occasional compiler joke",
      "hedging": "low — states preferences directly",
      "contrarianism": "mainstream Rust views, slightly pro-unsafe-when-necessary"
    },
    "writing_quirks": [
      "Prefers 'yeah' to 'yes'",
      "Uses code-formatted inline references (`Rc<RefCell<T>>`)",
      "Sometimes starts replies with 'FWIW'",
      "Ends long replies with a one-line summary"
    ]
  },
  "karma": {"post": 342, "comment": 1280},
  "proxy_assigned": "proxy-03 (DE residential)",
  "status": "warming_up"
}
```

### 2.2 — Voice Distinctness Verification

Before deploying personas, verify they're stylistically distinct:

```python
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

def verify_voice_distinctness(persona_samples):
    """Check that personas write differently from each other."""
    vectorizer = TfidfVectorizer(ngram_range=(1, 3), max_features=1000)
    tfidf = vectorizer.fit_transform(persona_samples)
    similarity = cosine_similarity(tfidf)

    issues = []
    for i in range(len(persona_samples)):
        for j in range(i+1, len(persona_samples)):
            if similarity[i][j] > 0.85:
                issues.append(f"Persona {i} and {j} too similar ({similarity[i][j]:.2f})")

    return {"distinct": len(issues) == 0, "issues": issues}
```

Regenerate any persona that scores >0.85 similarity with another.

### 2.3 — Warm-Up Protocol (Style-Matched)

All warm-up activity must match the forum's style. Use the forum fingerprint
to guide comment generation during warm-up:

**Week 1:**
- 2-3 comments/day, spread across 3-4 threads
- Each comment must pass the style verification gate (Phase 0.5)
- Comments must be genuine contributions — no promotion at all
- Build 10-50 karma

**Week 2:**
- 1-2 posts/day in non-target communities (genuine, style-matched)
- Continue commenting in target community
- Post type: question, observation, or resource

**Week 3+:**
- Account ready for campaign
- Continue non-promotional activity at 3:1 ratio

### 2.4 — IP & Browser Isolation

Different forum accounts need clean separation:

```
Tool: browser-automation skill (Playwright with separate contexts)
Tool: ProxyEmpire (residential proxies, one IP per persona)
Tool: playwright-stealth (pip install playwright-stealth)
Reference: puppeteer-extra-plugin-stealth (JS ecosystem alternative)
```

**Playwright context per persona:**

```python
from playwright.sync_api import sync_playwright
from playwright_stealth import Stealth

# One context per persona — completely isolated
context_configs = {
    "persona_alpha": {
        "proxy": "http://user-alpha:pass@proxy1.empire.io:5000",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...",
        "viewport": {"width": 1920, "height": 1080},
        "timezone_id": "America/New_York",
        "locale": "en-US",
        "storage_state": "profiles/alpha/cookies.json",
    },
    "persona_beta": {
        "proxy": "http://user-beta:pass@proxy2.empire.io:5000",
        # ... different config
    },
}

# Launch with stealth
for persona_id, config in context_configs.items():
    context = browser.new_context(**config)
    Stealth().apply_stealth_sync(context)  # or async
```

See `browser-automation` skill for full anti-detection setup (fingerprint
overrides, human-like behavior, account warming, SMS verification).

## Phase 3: Content Generation (Style-Matched)

### 3.1 — Post Type Selection

Match the post type to the forum's top-performing formats:

| Post Type | Best For | Style Match Required |
|-----------|----------|---------------------|
| Problem → Solution | SaaS, tools, services | Technical depth matching |
| "I built X" (transparent) | Indie products, OSS | Hacker authenticity |
| Resource share | Content sites, tools | Enthusiasm matching |
| Case study / results | B2B, productivity | Data-density matching |
| Hot take / contrarian | Thought leadership | Argument style matching |
| Question → Answer (alt) | Soft promotion | Curiosity matching |
| News + commentary | Content, traffic | Timeliness |

### 3.2 — Post Structure (Forum-Native Format)

Generate using the forum's fingerprint as constraint. The DeepSeek V4 Pro model
handles this with the style rules as a system prompt:

```
SYSTEM: You are writing a post for r/SUBREDDIT. Match these style rules exactly:

READABILITY: Flesch-Kincaid grade 7.2
SENTENCE RHYTHM: Average 16 words. Mix of 4-8 word and 12-20 word sentences.
  NO sentences over 30 words.
FORMATTING: Bold is rare. Bullet lists are common. Code blocks are frequent.
  NO emoji. NO markdown headers.
TONE: Direct, slightly irreverent. First-person. Deadpan humor.
  NO corporate speak. NO formal introductions.
VOCABULARY: Use community jargon naturally. NO Tier 1 AI vocabulary (delve,
  tapestry, crucial, comprehensive, meticulous, embark, robust, seamless).
OPENINGS: Start with a hook, not an introduction.
CLOSINGS: End with a question or TL;DR. Add "Edit:" for follow-ups.
CONTENT RULES: 80% genuine value, 20% mention of the thing. One link,
  naturally placed, never in the first paragraph. No UTM parameters.
```

### 3.3 — AI Tell Removal

After drafting, run the `humanizer` skill's 28-pattern detection:

```
Load: humanizer

Run on the draft:
- Strip Tier 1/2 vocabulary
- Kill banned phrases
- Remove chatbot artifacts
- Fix hedging and filler
- Verify zero em dashes
```

Then run the `agentic-humanizer` 5-pass rewrite if deeper polishing is needed.

### 3.4 — Title Optimization (Style-Aware)

Generate titles that match the forum's title conventions:

```python
# Extract title patterns from corpus
def extract_title_patterns(corpus):
    """Analyze what title formats perform best in this forum."""
    patterns = {
        "question_titles": [],
        "how_i_titles": [],
        "psa_titles": [],
        "hot_take_titles": [],
        "resource_titles": [],
    }
    for post in corpus:
        title = post["title"]
        if "?" in title:
            patterns["question_titles"].append((title, post["score"]))
        if title.lower().startswith(("how i", "how we")):
            patterns["how_i_titles"].append((title, post["score"]))
        # ... more pattern detection

    # Return best-performing patterns
    return {k: sorted(v, key=lambda x: x[1], reverse=True)[:5] for k, v in patterns.items()}
```

Present top 3 title candidates to the user, scored by pattern match + predicted performance.

## Phase 4: Multi-Account Comment Orchestration

### 4.1 — Three-Wave Strategy (Style-Calibrated)

Each persona's comments must pass style verification. Comments should be
indistinguishable from real forum members.

**Wave 1: Validation (30-60 min after posting)**

Persona B (enthusiast):
- Style: matches forum fingerprint, slightly more enthusiastic than average
- Content: "This is exactly what I needed. Been struggling with [pain point]
  for [timeframe]. Quick question — [edge case]?"

Persona C (comparison shopper):
- Style: matches forum fingerprint, analytical
- Content: "Interesting. I've been using [alternative] but [specific pain point]
  is driving me crazy. How does this handle [technical detail]?"

**Wave 2: Discussion (2-6 hours)**

Persona D (skeptical expert):
- Style: matches forum fingerprint, slightly contrarian
- Content: "How does this compare to [well-known tool] on [specific metric]?
  I ran benchmarks on [alternative] last month and got [specific number]."

OP response: Answer substantively. Share specific numbers, limitations, trade-offs.

Persona B follow-up: "Thanks for the detailed answer. One more thing — [deeper question]."

**Wave 3: Social Proof (6-24 hours)**

Persona E (late adopter):
- "Bookmarked. Been looking for something like this since [old tool] died."

Persona F (recent convert):
- "Just tried it — [specific feature] alone is worth it. The [detail] is better
  than I expected."

### 4.2 — Comment Generation Pipeline

```
1. Load forum linguistic fingerprint
2. Load persona voice calibration
3. Generate comment with DeepSeek V4 Pro (style-constrained prompt)
4. Run style verification (Phase 0.5)
5. Run humanizer (strip AI tells)
6. Run voice distinctness check against other persona comments
7. Final human review
```

### 4.3 — API Posting (PRAW Integration)

For Reddit, use PRAW instead of browser automation when possible
(browser is for account creation/warming; PRAW is for posting):

```python
import praw

def post_comment(persona_config, submission_id, comment_text):
    """Post a comment as a specific persona via PRAW."""
    reddit = praw.Reddit(
        client_id=persona_config["client_id"],
        client_secret=persona_config["client_secret"],
        user_agent=persona_config["user_agent"],
        username=persona_config["username"],
        password=persona_config["password"],
    )

    submission = reddit.submission(id=submission_id)
    comment = submission.reply(comment_text)
    return {"id": comment.id, "permalink": comment.permalink}
```

**Snoowrap (JS alternative):**

```javascript
const snoowrap = require('snoowrap');
const r = new snoowrap({
    userAgent: 'forum-bot/1.0',
    clientId: '...',
    clientSecret: '...',
    username: 'persona_alpha',
    password: '...'
});

r.getSubmission('post_id').reply('comment text');
```

## Phase 5: Traffic & Trust Conversion

### 5.1 — Trust Funnel

```
Organic Discovery → Style Recognition ("this sounds legit") → Interest →
Trust (OP sounds like us) → Click (natural curiosity) → Conversion
```

### 5.2 — Link Strategy

- **Primary link:** In OP body, once, naturally. Never first paragraph.
- **Secondary links:** In OP replies, only when genuinely answering a question.
- **NO links in persona comments.**
- Use clean URLs (no UTMs, no affiliate tags).

### 5.3 — Analytics

Track via PRAW:

```python
def get_post_metrics(reddit, post_id):
    submission = reddit.submission(id=post_id)
    return {
        "score": submission.score,
        "upvote_ratio": submission.upvote_ratio,
        "num_comments": submission.num_comments,
        "view_count": submission.view_count,  # if available
        "created_utc": submission.created_utc,
    }
```

**Additional analytics tools:**
- SocialGrep (socialgrep.com) — Reddit search and analytics
- reddit-trends (various GitHub repos) — subreddit growth tracking
- Custom URL shortener with click tracking (your own domain + analytics)

## Phase 6: Anti-Detection

### 6.1 — Detection Vectors & Mitigations

| Vector | Tool/Mitigation |
|--------|----------------|
| IP clustering | ProxyEmpire per persona (browser-automation skill) |
| Browser fingerprinting | playwright-stealth, puppeteer-extra-plugin-stealth |
| Stylometric similarity | Voice distinctness verification (Phase 2.2) |
| Temporal clustering | Stagger account creation + activity |
| Link velocity | 5:1 no-link to link post ratio |
| Vote rings | Max 2-3 upvotes from personas, spread over hours |
| Karma farming | Quality warm-up, not rapid low-effort |
| Cross-referencing | Limit persona overlap to 1-2 campaigns |

### 6.2 — Reddit Shadowban Detection

```python
def check_shadowban(username):
    """Check if a Reddit account is shadowbanned."""
    import requests
    r = requests.get(
        f"https://www.reddit.com/user/{username}/about.json",
        headers={"User-Agent": "shadowban-checker/1.0"}
    )
    if r.status_code == 404:
        return {"status": "shadowbanned", "note": "Profile not found — likely shadowbanned"}
    elif r.status_code == 200:
        data = r.json()
        return {"status": "active", "karma": data.get("data", {}).get("total_karma", 0)}
    return {"status": "unknown", "http_status": r.status_code}
```

### 6.3 — Pre-Flight Checklist

- [ ] Phase 0 completed: corpus extracted, fingerprint generated, style rules defined
- [ ] All persona voice calibrations verified distinct (similarity <0.85)
- [ ] OP account has >2 weeks of style-matched post/comment history
- [ ] OP account has posted in target community before (3+ times)
- [ ] Persona accounts have distinct IPs (proxies assigned in browser-automation)
- [ ] Persona accounts have distinct browser contexts (Playwright)
- [ ] Persona accounts have >1 week of style-matched warm-up activity
- [ ] No persona has interacted with any other persona recently
- [ ] OP link-to-no-link post ratio is >1:5
- [ ] OP draft passes style verification (Phase 0.5)
- [ ] All comments pass style verification
- [ ] All content passes humanizer (zero AI tells)
- [ ] Post complies with forum's self-promotion rules
- [ ] Link is clean (no UTMs, no affiliate tags)
- [ ] Timing plan accounts for forum's peak hours
- [ ] Shadowban check passed for all accounts

## Tool Installation Summary

```bash
# Python tools
pip install praw asyncpraw textstat nltk spacy
python -m spacy download en_core_web_sm

# JS tools (optional, for snoowrap + stealth)
npm install snoowrap puppeteer-extra puppeteer-extra-plugin-stealth

# Playwright stealth (Python)
pip install playwright-stealth

# NLP
pip install scikit-learn  # for TF-IDF voice distinctness

# Reddit API setup: https://www.reddit.com/prefs/apps
# Create "script" type app for each persona
# Note: client_id, client_secret, username, password per persona
```

## Model Routing

- **MiMo V2.5**: corpus extraction, PRAW data collection, readability calculation,
  voice distinctness scoring, style verification checks, timing calculations,
  schema validation, shadowban checks, proxy health checks
- **DeepSeek V4 Pro**: linguistic fingerprint interpretation, style rule generation,
  persona design, post/comment drafting with style constraints, narrative analysis,
  title optimization, campaign strategy, anti-detection reasoning

## Common Pitfalls

1. **Skipping Phase 0.** The #1 reason forum posts fail. If you don't extract
   the forum's style fingerprint, your posts will sound foreign. Style analysis
   is not optional.

2. **Over-matching the style.** Posts that hit EVERY style marker look like
   parodies. Deliberately skip 1-2 markers per post. Real community members
   don't recite a checklist.

3. **Identical writing voices.** The voice distinctness check (Phase 2.2) is
   mandatory. If two personas score >0.85 similarity, redesign one.

4. **Rushing the warm-up.** 2-week minimum. No exceptions for Reddit.

5. **Neglecting real replies.** Staged comments are scaffolding. Reply to every
   real commenter within 12 hours. Be genuinely helpful, not promotional.

6. **Cross-contamination.** Same proxy + same browser = same fingerprint.
   Full isolation per persona.

7. **Campaign density.** Don't run the same product across 5 subreddits in one
   week. Stagger by 1-2 weeks.

8. **Using browser for API calls.** PRAW is faster, cheaper, and doesn't trigger
   bot detection for posting. Browser is for account creation and warming.
   API is for content deployment.

9. **Ignoring the style guide during warm-up.** Every warm-up comment must also
   match the forum's style. Inconsistent style history is a detection vector.

10. **Aging the wrong way.** Comments during warm-up that are obviously
    AI-generated build a trail of evidence against the account. Style-match
    everything.

## Verification Checklist

- [ ] Phase 0 completed: 50-100 posts extracted, linguistic fingerprint generated
- [ ] Style rules document created and reviewed
- [ ] Forum fingerprint passed through voice-humanizer for deeper analysis
- [ ] Narrative map generated via narrative-mimicry skill
- [ ] 3-5 target forums identified, scored, and documented with rules
- [ ] OP persona created with forum-calibrated voice
- [ ] 2-4 commenter personas created with verified distinct voices (<0.85 similarity)
- [ ] Proxies assigned and tested for each persona (browser-automation)
- [ ] Browser isolation confirmed (separate Playwright contexts)
- [ ] OP draft written with style-matched 5-part structure
- [ ] OP draft passes style verification (Phase 0.5)
- [ ] OP draft passes humanizer (zero AI tells)
- [ ] 5-10 title variants generated, top 2-3 selected by forum pattern match
- [ ] Three-wave comment plan drafted with style-matched, voice-distinct comments
- [ ] All comments pass style verification
- [ ] Timing plan set for forum's peak activity hours
- [ ] Link is clean (no UTMs, no affiliate tags)
- [ ] Pre-flight checklist completed for all accounts
- [ ] Shadowban check passed for all accounts
- [ ] API credentials ready (PRAW/snoowrap per persona)
- [ ] Campaign tracking set up (PRAW metrics + URL monitoring)
