home / skills / cdeistopened / opened-vault / x-posting

x-posting skill

/.claude/skills/x-posting

This skill helps you batch and schedule X/Twitter posts from OpenEd content, including guest tagging and template-guided copy generation.

npx playbooks add skill cdeistopened/opened-vault --skill x-posting

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
8.0 KB
---
name: x-posting
description: Post and schedule content to X/Twitter. Use when batch processing social posts, promoting podcasts/blogs, or scheduling content. Handles guest tagging, template matching, and getlate.dev API integration.
---

# X Posting Workflow

End-to-end workflow for creating, approving, and scheduling X/Twitter posts from OpenEd content.

## When to Use

- Batch processing X posts from recent content
- Promoting podcast episodes or blog posts
- Scheduling a week of social content
- Any X posting that involves guest tagging

## Prerequisites

- `GETLATE_API_KEY` in `.env`
- Connected Twitter account in getlate.dev (@OpenEdHQ)

---

## The Workflow

### Step 1: Find Content

Search the Master Content Database for recent/relevant content:

```bash
# Find recent podcasts
ls "Content/Master Content Database/Podcasts/" | head -20

# Find recent blog posts
ls "Content/Master Content Database/Blog Posts/" | head -20
```

Read source files to extract:
- Key insights and quotes
- Guest names
- Actual URLs (from frontmatter `url:` field)

**CRITICAL:** Never hallucinate URLs. Always pull from the source file's frontmatter.

---

### Step 2: Find Guest X Handles

**Before writing any post featuring a guest:**

1. Web search: `"[Guest Name] [Company] Twitter X account"`
2. Verify it's the correct person (check bio)
3. Note both personal handle AND company handle if applicable

Common OpenEd guest handles:
- See `Studio/Social_Scheduling.md` for previously found handles
- Add new handles to the reference table when found

---

### Step 3: Framework Fitting via Sub-Agents

**CRITICAL: Spawn a sub-agent for EACH piece of content.**

This is token-heavy but ensures quality. Each sub-agent does deep framework fitting rather than surface-level template matching.

**Sub-Agent Prompt Template:**

```
You are writing X/Twitter posts for OpenEd. Your job is DEEP FRAMEWORK FITTING - matching this concept to proven templates that amplify it.

## Source Content
[Paste the full content or key excerpts]

## Guest Info
- Name: [Guest Name]
- X Handle: @[handle]
- Company: [Company] (@[company_handle] if applicable)

## URL (use exactly)
[URL from frontmatter]

## Your Task

### Phase 1: Concept Extraction
Extract from this content:
1. Core insight (one sentence)
2. Emotional hook (what feeling does this evoke?)
3. Most quotable moment
4. Surprising fact or statistic
5. Contrarian angle (what does this challenge?)

### Phase 2: Template Review
Read the FULL post-structures.md file. Do not skim.

For this concept, evaluate AT LEAST these template categories:
- Commentary (quote + translation + explanation)
- Contrast Evaluation (X overrated, Y underrated)
- Paradox Hook (present contradiction)
- Comparison with percentages (numbers + question)
- Personal Story (setup → conflict → resolution)
- One Sentence Comparison
- Behavior Dichotomy
- Binary Framing Hook
- Counterintuitive Statement Hook

For each potentially fitting template:
1. Name the template
2. Explain WHY it might work for this concept
3. Rate fit: Strong / Moderate / Weak
4. Draft a quick test version

### Phase 3: Select and Write
Choose 2-3 BEST fitting templates. Write full post variations using the EXACT template structure.

### Phase 4: Voice Validation
For each draft, check against AI-tells:

HARD BLOCKS (reject and rewrite if present):
- Correlative constructions ("X isn't just Y - it's Z")
- Split correlatives ("It wasn't about X. It was about Y.")
- Staccato fragments ("No X. No Y. Just Z.")
- Setup phrases ("Here's the thing:", "The best part?")
- Triple adjective patterns
- Thesaurus words (utilize, leverage, comprehensive, crucial)

VOICE CHECK:
- Does this sound like a person talking or performing "good writing"?
- Is this something you'd actually text to a friend?
- Does it follow the template structure or drift into generic copy?

### Output Format
For each post option:
1. Template used: [Name]
2. Why this template: [1-2 sentences]
3. Post:
> [The actual post text]
>
> [link]
4. Voice validation: [Pass/Fail with notes]
```

**Launch sub-agents in parallel** - one per content piece. They will return structured options ready for the scheduling file.

---

### Step 4: Compile Scheduling File

Collect sub-agent outputs into `Studio/Social_Scheduling.md`:

```markdown
# X Post Scheduling Queue

**Created:** [date]
**Status:** Awaiting approval

---

### 1. [Content Title] - @[guest_handle]

**URL:** [actual URL from source]

**Option A - [Template Name]:**
> [Post content]
>
> [link]

Template reasoning: [Why this template fits]

- [ ] Approve Option A

**Option B - [Template Name]:**
> [Post content]
>
> [link]

Template reasoning: [Why this template fits]

- [ ] Approve Option B
```

User marks approvals with `[X]` and adds notes in `{NOTES: ...}`.

---

### Step 5: Voice Validation (Final Check)

Before posting/scheduling, run final validation:

**Hard Blocks:**
- [ ] No correlative constructions ("X isn't just Y - it's Z")
- [ ] No split correlatives ("X wasn't about Y. It was about Z.")
- [ ] No staccato fragments ("No X. No Y. Just Z.")
- [ ] No setup phrases ("Here's the thing:", "The best part?")

**Soft Checks:**
- [ ] Sounds like a person, not a copywriter
- [ ] Uses actual template structure (can identify which one)
- [ ] Guest tagged correctly
- [ ] URL is real (from source file)

---

### Step 6: Post and Schedule via getlate.dev

**Post immediately:**
```bash
python3 agents/post_tweet.py '[tweet content]'
```

**Schedule for future:**
```python
import os
import requests
from pathlib import Path
from dotenv import load_dotenv

load_dotenv(Path(__file__).parent.parent / ".env")

api_key = os.getenv("GETLATE_API_KEY")
base_url = "https://getlate.dev/api/v1"
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}

# Get account ID
response = requests.get(f"{base_url}/accounts", headers=headers)
accounts = response.json().get("accounts", [])
twitter_account = next((a for a in accounts if a.get("platform") == "twitter"), None)
account_id = twitter_account.get("_id")

# Schedule post (9am ET = 14:00 UTC in winter)
post_data = {
    "platforms": [{"platform": "twitter", "accountId": account_id}],
    "content": "Your tweet content here",
    "scheduledFor": "2026-01-15T14:00:00Z"  # ISO 8601 format
}

response = requests.post(f"{base_url}/posts", headers=headers, json=post_data)
```

**Time conversion:**
- 9am ET (winter) = 14:00 UTC
- 9am ET (summer/DST) = 13:00 UTC

---

## Quick Reference

### getlate.dev API

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/accounts` | GET | List connected accounts |
| `/posts` | POST | Create/schedule post |

**Post payload:**
```json
{
  "platforms": [{"platform": "twitter", "accountId": "..."}],
  "content": "Tweet text",
  "publishNow": true,           // OR
  "scheduledFor": "ISO-8601"    // for scheduling
}
```

### Best Posting Times (ET)

- 8-9am - Morning commute
- 12-1pm - Lunch break
- 7-8pm - Evening wind-down

### Character Limits

- Optimal: 70-100 characters
- Max: 280 characters
- With link: ~250 characters of text

---

## Sub-Agent Required Reading

Each sub-agent MUST read these files before writing posts:

| File | Purpose | Tokens |
|------|---------|--------|
| `.claude/skills/text-content/references/templates/post-structures.md` | 100+ template structures | ~4000 |
| `.claude/skills/ai-tells/SKILL.md` | Voice constraints | ~200 |
| `.claude/skills/ai-tells/references/pirate-wires-examples.md` | Voice examples | ~1500 |
| Source content file | The actual content to promote | varies |

**Why this matters:** The quality difference between skimming templates and deeply reading them is the difference between generic AI copy and posts that actually follow proven structures.

---

## Related Skills

- `text-content` - Template library and framework fitting
- `ai-tells` - Voice validation
- `ghostwriter` - Deeper voice guidance

---

## Files

- `agents/post_tweet.py` - Single tweet posting
- `agents/test_tweet.py` - API testing
- `Studio/Social_Scheduling.md` - Current queue

---

*Last updated: 2026-01-14 (v2 - added sub-agent framework fitting)*

Overview

This skill posts and schedules content to X (formerly Twitter) using a structured, approval-driven workflow. It extracts core insights and guest handles from your source files, runs parallel sub-agents to fit content to proven templates, and publishes or schedules via the getlate.dev API. Ideal for batch processing, guest tagging, and predictable social queues.

How this skill works

The skill scans your master content files to extract URLs, quotes, guest names, and core insights, then spawns a sub-agent per content piece to perform deep framework fitting against multiple template categories. Sub-agents return 2–3 vetted post variations with voice validation. Approved options are compiled into a scheduling queue and posted immediately or scheduled through getlate.dev using your API key.

When to use it

  • Batch-processing many social posts from recent content
  • Promoting podcast episodes, blog posts, or interviews
  • Scheduling a week of X content ahead of time
  • Any post that must correctly tag guests or companies
  • When you need consistent voice and template-driven testing

Best practices

  • Always pull the URL from the source file frontmatter—never guess or invent links.
  • Verify guest X handles via web search and record both personal and company handles.
  • Launch one sub-agent per content piece for deep template fitting; parallel processing improves quality.
  • Run the final voice validation checklist to remove banned constructions before scheduling.
  • Use the getlate.dev account lookup to find the correct accountId before posting or scheduling.

Example use cases

  • Create a week-long X schedule promoting five recent podcast episodes with guest tags and quotable lines.
  • Convert a new blog post into three template-tested tweet variations and queue them for optimal ET times.
  • Batch-prepare social posts for a product launch, assigning personal and company handles where relevant.
  • Schedule evergreen content at 9am ET consistently by converting times to UTC when creating scheduled posts.

FAQ

What credentials are required to post or schedule?

You must set GETLATE_API_KEY in your environment; the skill uses getlate.dev to post and schedule to the connected X account.

How are guest handles verified?

Search the web for the guest name plus company, confirm via the profile bio, and record both personal and company handles in your reference table.