Narrative Detection & Mimicry
Detect the dominant narrative structures, rhetorical patterns, and ideological frames in a target community — then generate new posts that authentically participate in those narratives.
What this skill does (and doesn't)
This skill detects what a community believes and how they argue — the
narrative layer above individual writing style. It does NOT clone one
person's voice (use voice-humanizer for that). It does NOT just remove
AI tells from text (use humanizer for that). It does NOT manage a
publishing calendar (use x-posting-agent for that).
What it does: observe what's resonating → extract why → generate more of it, in your voice.
| Existing skill | Scope | This skill fills the gap |
|---|---|---|
voice-humanizer |
Copies one person's writing style | Doesn't know WHAT a community talks about |
humanizer |
Removes AI language patterns | Doesn't know which narratives resonate |
x-posting-agent |
Publishing pipeline + campaigns | Generates top-down from specs, not bottom-up from patterns |
When to use
- User says "analyze narratives in the transhumanism space"
- User wants to know what arguments/angles are working in a community
- User asks "generate posts that fit what this community talks about"
- User provides a corpus (links, screenshots, text) and wants mimicry
- User wants to expand into a new domain and needs to understand the conversation
Architecture
~/.hermes/narrative-mimicry/
├── domains.json — registry of analyzed domains
├── <domain-slug>/ — e.g., transhumanism, nootropics
│ ├── corpus/
│ │ └── <iso-date>-posts.json — raw collected posts
│ ├── narrative_taxonomy.json — Phase 1 output
│ ├── narrative_decomposition.json — Phase 2 output
│ ├── drafts/
│ │ └── <iso-date>-<narrative>-<variant>.json
│ ├── published/
│ │ └── <iso-date>-<content-id>.json
│ └── performance/
│ └── <iso-date>-metrics.json
└── global_blacklist.json — narratives never to mimic
Phase 1: Narrative Detection
Step 1.1 — Resolve the domain
If the user names a domain (e.g., "transhumanism Twitter"), normalize to a
kebab-case slug. Check domains.json to see if this domain has been analyzed
before.
// domains.json
{
"transhumanism": {
"slug": "transhumanism",
"display_name": "Transhumanism / Longevity / BCI on X",
"source_platform": "x",
"last_analyzed": "2026-07-15T10:00:00Z",
"corpus_size": 38,
"narrative_count": 7,
"status": "active"
}
}
If the domain exists and was analyzed <7 days ago, ask whether to reuse or refresh. If >14 days, warn that narratives may be stale and recommend refresh.
Step 1.2 — Gather the corpus
Path A: X/Twitter domain (via xurl CLI)
Search for high-engagement posts in the target domain:
# Collect 30-50 posts. Filter for engagement.
xurl search "<domain keywords> min_faves:20" --count 20 --auth oauth1
xurl search "<domain keywords> min_retweets:10" --count 20 --auth oauth1
Pull the full thread context for any highly-engaged posts. Also pull top replies — audience reaction is signal.
Save raw corpus to corpus/<iso-date>-posts.json:
[
{
"id": "platform_post_id",
"author_handle": "@user",
"text": "full post text",
"likes": 142,
"reposts": 23,
"replies": 18,
"timestamp": "ISO 8601",
"is_thread": false,
"thread_parts": [],
"top_replies": ["reply text 1", "reply text 2"]
}
]
Path B: User-provided corpus
User pastes links, screenshots, or raw text. Validate:
- Minimum 15 items (less = unreliable signal)
- Diverse authors (at least 5 different sources, or the corpus is just one person's worldview)
- Recent (majority from last 30 days unless historical analysis is intentional)
If corpus is insufficient, tell the user exactly what's missing and ask for more.
Path C: Web research (for non-X communities)
Use web_search to find recent high-engagement content from the target community (Reddit threads, blog posts, forum discussions, newsletter issues). Same minimum thresholds apply.
Step 1.3 — Extract narratives
Run the corpus through this extraction prompt internally:
You are analyzing a corpus of posts from a specific community to identify
recurring narrative structures. A "narrative" is not a topic — it's a
shared belief, argument pattern, or framing that community members
repeatedly use.
Topics are WHAT they talk about. Narratives are HOW they talk about it
and WHAT THEY BELIEVE about it.
For each recurring narrative you detect, return:
{
"narrative_id": "kebab-case-label",
"label": "5-8 word name",
"core_claim": "The central assertion in one sentence",
"frequency": {"count": N, "percentage": X.X},
"emotional_driver": "What feeling does expressing this activate?",
"ingroup_signal": "What belief or identity does this mark?",
"outgroup_opposition": "Who or what is it positioned against?",
"key_vocabulary": ["phrase1", "phrase2", "..."],
"best_example": "Copy the single best real example from the corpus",
"example_post_id": "id from corpus",
"engagement_correlation": "high|medium|low|unclear",
"is_growing": true/false,
"counter_narratives": ["narrative_id that opposes this one"]
}
Return a JSON array of narratives, sorted by frequency descending.
Group closely related narratives together. If two narratives are really
the same thing with different vocabulary, merge them and note the
vocabulary variants.
Step 1.4 — Build the taxonomy
Organize extracted narratives into tiers:
- Dominant (>15% frequency): gravitational center. Must understand these.
- Established (5-15%): respected positions within the in-group.
- Counter-narratives (present but opposed to dominant): dissent that's still inside the tent. These are valuable — they let you participate in debates authentically.
- Fringe (<5%): niche positions. May be growing. Worth tracking.
- Declining (was common, now fading): avoid. Marks you as out of date.
- External attacks (narratives from opponents about the community): know these so you don't accidentally amplify them.
Save to narrative_taxonomy.json:
{
"domain": "transhumanism",
"analyzed_at": "ISO 8601",
"corpus_size": 38,
"source": "x_search",
"fresh_until": "ISO 8601 + 14 days",
"narratives": {
"dominant": [{...}, ...],
"established": [{...}, ...],
"counter": [{...}, ...],
"fringe": [{...}, ...],
"declining": [{...}, ...],
"external_attacks": [{...}, ...]
}
}
Step 1.5 — Present to user
Show a compact summary:
NARRATIVE TAXONOMY: transhumanism
38 posts analyzed | 7 narratives detected | Fresh until July 29
DOMINANT (2)
AGI-is-coming-faster-than-expected (26%)
"Timelines are compressing and nobody in power is acting like it"
human-enhancement-is-inevitable (18%)
"The question isn't if we'll augment, it's who controls the augments"
ESTABLISHED (3)
...
COUNTER (1)
...
FRINGE (1)
...
Any narratives to blacklist? Any you want me to prioritize for drafting?
Phase 2: Narrative Decomposition
For each narrative the user wants to generate content for, decompose it into reusable structural components.
Step 2.1 — Run decomposition
For each target narrative, run this prompt internally:
Decompose this narrative into its structural components. Be specific and
observable — no generic labels.
Narrative: {label}
Core claim: {core_claim}
Best example: {best_example}
Return:
{
"narrative_id": "...",
"opening_moves": [
{
"pattern": "description of how posts open",
"example": "real opening from corpus",
"effectiveness": "why this works for this audience"
}
],
"evidence_patterns": [
{
"pattern": "how claims are supported",
"example": "real evidence move from corpus"
}
],
"emotional_arc": {
"starts_with": "emotion",
"turns_to": "emotion",
"resolves_with": "emotion or call to action"
},
"resolution_types": ["prediction", "call to action", "reframing", "question"],
"metaphor_families": ["recurring metaphors used"],
"sacred_concepts": ["what cannot be questioned in this narrative"],
"forbidden_moves": ["what gets you dismissed when using this narrative"],
"humor_register": "dark|ironic|earnest|deadpan|none",
"status_signals": ["how insiders demonstrate belonging"],
"length_pattern": {
"typical": "short_post|thread|long_post",
"avg_chars": N,
"notes": "observation about length patterns"
},
"audience_model": {
"primary_audience": "who this speaks to",
"what_they_already_believe": "...",
"what_they_want_to_be_true": "...",
"what_they_are_tired_of": "...",
"desired_action": "what feeling this makes people want to do"
}
}
Step 2.2 — Cross-narrative patterns
After decomposing all target narratives, identify:
- Shared opening moves across narratives (these are community-wide tics)
- Contradictory sacred concepts between narratives (tension points you can exploit for authentic-seeming posts that acknowledge complexity)
- Narrative blind spots — what's true but never said? (high-value territory for original content)
Save to narrative_decomposition.json.
Phase 3: Mimicry Generation
Step 3.1 — Select narratives to generate for
User may specify which narratives to target. If not, default to:
- 1 dominant narrative
- 1 established narrative (different from dominant)
- 1 counter-narrative (if one exists — shows range)
Step 3.2 — For each narrative, find a fresh angle
Before generating, identify what's new THIS WEEK that connects to the narrative. Check:
- Recent news in the domain (web_search)
- Recent posts from key accounts (xurl search)
- New papers, data, or events
The post must feel timely, not evergreen. Evergreen posts in fast-moving communities read as AI-generated.
Step 3.3 — Generate posts
Run this prompt for each narrative+angle pair:
Generate a post (or short thread) that authentically participates in
this community narrative. You are writing as YOURSELF — not as a generic
community member. Use your own voice, your own perspective. The narrative
provides the FRAME, not the script.
NARRATIVE: {label}
CORE CLAIM: {core_claim}
EMOTIONAL ARC: {starts_with} → {turns_to} → {resolves_with}
OPENING MOVES THAT WORK: {opening_moves}
FORBIDDEN MOVES: {forbidden_moves}
KEY VOCABULARY: {key_vocabulary} (use NATURALLY, not as a checklist)
FRESH ANGLE: {this week's connection}
YOUR VOICE: first-person authentic, builder's perspective, skeptical of
hype but bullish on substance
RULES:
- Must pass as written by a real community member, not a bot
- Must NOT simply restate the narrative — add something new
- Must NOT be a parody or caricature
- Must feel timely, not like it could have been posted any week
- Target 250-260 chars (not 275-280 — leave editing buffer)
- Vary from your last posts in this domain (check published/ for patterns)
- If you use key vocabulary, use 2-3 terms max, not all of them
- End with something that invites response (question, prediction, hot take)
Return:
{
"narrative_id": "...",
"variant": "provocation|connection|synthesis",
"text": "post text",
"thread_parts": ["if thread, array of parts"],
"fresh_angle_used": "what makes this timely",
"opening_move_used": "which pattern from decomposition",
"narrative_signals_hit": ["which signals are present (keep to 2-3)"],
"narrative_signals_avoided": ["which signals were deliberately skipped to avoid overfit"]
}
Step 3.4 — Generate variants
For each narrative, produce up to 3 variants:
- Provocation: pushes the narrative slightly further. Invites debate. "Here's the thing nobody wants to say about [sacred concept]..."
- Connection: links the narrative to something personal or concrete. "I was [doing thing] when I realized [narrative insight]..."
- Synthesis: connects this narrative to a different one in the taxonomy. "The reason [narrative A] keeps failing is [narrative B]..."
Not every narrative needs all three variants. Use judgment.
Step 3.5 — Thread generation (when appropriate)
A narrative benefits from a thread when:
- It involves a chain of reasoning that doesn't compress to 280 chars
- The evidence pattern requires showing work
- The emotional arc needs buildup, not just a punchline
Thread structure:
- Hook: opening move, self-contained, makes you want to click "show more"
- Context: why this matters now
- Evidence: the receipts (paper, data, event, quote)
- The turn: reframe, prediction, implication, or tension
- Resolution: what to do with this — call to action, question, or "here's what I'm watching next"
Each part must have a distinct function. Never restate the same idea across parts.
Save drafts to drafts/<iso-date>-<narrative>-<variant>.json.
Phase 4: Quality Control
Step 4.1 — Narrative fit scoring
Rate each draft:
| Criterion | Scale | Threshold |
|---|---|---|
| Narrative authenticity (would a real member write this?) | 1-10 | ≥7 |
| Freshness (does it add something new?) | 1-10 | ≥6 |
| Engagement potential (will it get shared/replied to?) | 1-10 | ≥6 |
| Outsider-risk (tells the author doesn't belong) | 1-10 | ≤3 |
| Overfit-risk (hits too many signals, feels like a checklist) | 1-10 | ≤4 |
| Self-plagiarism risk (too similar to recent published posts) | 1-10 | ≤3 |
Run this scoring internally against each draft. Flag anything that fails a threshold. Reject or revise.
Step 4.2 — Self-plagiarism check
Compare draft against published/ directory for the domain. If the draft
uses the same opening move as a post from the last 7 days, flag it. If the
core insight is the same as a post from the last 14 days, reject it.
This is why we save published posts — without this, you'll accidentally repeat yourself and the audience will notice.
Step 4.3 — Humanization pass
After narrative fit is confirmed, run the draft through the standard
humanization patterns from voice-humanizer:
- Strip Tier 1/2 vocabulary
- Kill banned phrases
- Remove chatbot artifacts
- Fix filler and hedging
- Vary sentence rhythm
- Add concrete specifics
- Zero em dashes (hard constraint)
The narrative mimicry handles WHAT you say. The humanization pass handles HOW you say it. Both are necessary.
Step 4.4 — Read-aloud test
The final gate: read the post aloud (mentally). If it sounds like a press release, rewrite it. If it sounds like you're trying too hard to sound like a community member, rewrite it. If it sounds like something you'd actually say in conversation, ship it.
Integration with x-posting-agent
When creating an X campaign for a domain that has a narrative taxonomy:
- Load
narrative_taxonomy.jsonfor the domain - Use dominant + established narratives as content pillars
- Use
narrative_decomposition.jsonopening moves as style guidance - Validate campaign drafts against narrative authenticity scoring
- After publishing, feed engagement metrics back to
performance/
Integration with voice-humanizer
After narrative mimicry generates a draft, the voice-humanizer pipeline
handles the final polish. These are separate concerns:
- Narrative match: Did I say the right thing for this community? (this skill)
- Voice match: Did I say it like myself? (voice-humanizer)
- Language quality: Did I remove AI tells? (humanizer)
Model routing
- MiMo V2.5: source gathering (search, scrape), corpus validation, engagement math, duplicate detection, character counting, self-plagiarism check, scoring calculations
- DeepSeek V4 Pro: narrative extraction (Phase 1.3), narrative decomposition (Phase 2.1), post generation (Phase 3.3), variant generation, quality scoring judgments, read-aloud assessment
Freshness policy
- Narrative taxonomy: refresh if >14 days old
- Narrative decomposition: refresh if >30 days old OR if taxonomy was refreshed
- Source corpus: keep for historical comparison, but new analysis uses fresh data
- Published posts: keep indefinitely (self-plagiarism prevention)
Pitfalls
Parody drift
Over-optimizing for narrative signals produces caricature. Signs: every post hits 4+ key vocabulary terms, emotional arc is too perfect, post reads like it was generated from a template. Fix: deliberately skip 1-2 obvious signals. Real community members don't recite the checklist.
Evergreen drift
Posts that could have been written any week. Signs: no reference to current events, no temporal anchor, vague "in recent years..." framing. Fix: require a specific fresh angle before generation. If you can't find one, don't generate for that narrative today.
Narrative clustering
Generating too many posts from the same narrative cluster makes the account feel one-dimensional. Fix: rotate across dominant, established, and counter-narratives. At most 40% of posts from any single narrative in a rolling 14-day window.
Detection by the community
If every post is too well-calibrated, sophisticated community members will notice. Fix: occasionally post something that only hits 1-2 narrative signals. Let some mess in. Not every post needs to be optimized.
Using outdated narratives
Communities evolve. A narrative that was dominant 3 months ago may now be
a cliché or a marker of being out of touch. Fix: respect the freshness
policy. If a narrative appears in declining, never generate from it.
Commands
/narrative analyze <domain>— full Phase 1: gather corpus + extract taxonomy/narrative refresh <domain>— re-analyze an existing domain/narrative show <domain>— display current taxonomy/narrative decompose <domain> <narrative_id>— Phase 2: decompose one narrative/narrative generate <domain> [narrative_id]— Phase 3: generate drafts/narrative review— show unscored drafts/narrative publish <draft_id>— send to x-posting-agent queue/narrative blacklist <domain> <narrative_id>— never generate from this narrative/narrative domains— list all analyzed domains
Global blacklist
global_blacklist.json contains narratives that should NEVER be mimicked,
regardless of domain. These are narratives the author considers harmful,
off-brand, or reputationally dangerous. Blacklisted narratives are skipped
during extraction — they won't appear in taxonomies.
{
"blacklisted_narratives": [],
"blacklisted_topics": [],
"blacklisted_phrasing_patterns": [],
"notes": "Add entries manually. Blacklisted items are silently dropped during extraction."
}
Add to this when you encounter narratives that are:
- Promoting harm (violence, self-harm, dangerous pseudoscience)
- Incompatible with the author's values
- Legally dangerous in the author's jurisdiction
- Associated with communities the author doesn't want to be linked to