diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 220bd06..0cf564c 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -16,7 +16,8 @@ "strict": false, "skills": [ "./skills/gemini-web", - "./skills/xhs-images" + "./skills/xhs-images", + "./skills/post-to-x" ] } ] diff --git a/skills/post-to-x/SKILL.md b/skills/post-to-x/SKILL.md new file mode 100644 index 0000000..7ffacaa --- /dev/null +++ b/skills/post-to-x/SKILL.md @@ -0,0 +1,339 @@ +--- +name: post-to-x +description: Post content and articles to X (Twitter). Supports regular posts with images and X Articles (long-form Markdown). Uses real Chrome with CDP to bypass anti-automation. +--- + +# Post to X (Twitter) + +Post content, images, and long-form articles to X using real Chrome browser (bypasses anti-bot detection). + +## Features + +- **Regular Posts**: Text + up to 4 images +- **X Articles**: Publish Markdown files with rich formatting and images (requires X Premium) + +## Usage + +```bash +# Post text only +/post-to-x "Your post content here" + +# Post with image +/post-to-x "Your post content" --image /path/to/image.png + +# Post with multiple images (up to 4) +/post-to-x "Your post content" --image img1.png --image img2.png + +# Actually submit the post +/post-to-x "Your post content" --submit +``` + +## Prerequisites + +- Google Chrome or Chromium installed +- `bun` installed (for running scripts) +- First run: log in to X in the opened browser window + +## Quick Start (Recommended) + +Use the `x-browser.ts` script directly: + +```bash +# Preview mode (doesn't post) +npx -y bun ./scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png + +# Actually post +npx -y bun ./scripts/x-browser.ts "Hello!" --image ./photo.png --submit +``` + +The script: +1. Launches real Chrome with anti-detection disabled +2. Uses persistent profile (only need to log in once) +3. Types text and pastes images via CDP +4. Waits 30s for preview (or posts immediately with `--submit`) + +## Manual Workflow + +If you prefer step-by-step control: + +### Step 1: Copy Image to Clipboard + +```bash +npx -y bun ./scripts/copy-to-clipboard.ts image /path/to/image.png +``` + +### Step 2: Use Playwright MCP (if Chrome session available) + +```bash +# Navigate +mcp__playwright__browser_navigate url="https://x.com/compose/post" + +# Get element refs +mcp__playwright__browser_snapshot + +# Type text +mcp__playwright__browser_click element="editor" ref="" +mcp__playwright__browser_type element="editor" ref="" text="Your content" + +# Paste image (after copying to clipboard) +mcp__playwright__browser_press_key key="Meta+v" # macOS +# or +mcp__playwright__browser_press_key key="Control+v" # Windows/Linux + +# Screenshot to verify +mcp__playwright__browser_take_screenshot filename="preview.png" +``` + +## Parameters + +| Parameter | Description | +|-----------|-------------| +| `` | Post content (positional argument) | +| `--image ` | Image file path (can be repeated, max 4) | +| `--submit` | Actually post (default: preview only) | +| `--profile ` | Custom Chrome profile directory | + +## Image Support + +- Formats: PNG, JPEG, GIF, WebP +- Max 4 images per post +- Images copied to system clipboard, then pasted via keyboard shortcut + +## Example Session + +``` +User: /post-to-x "Hello from Claude!" --image ./screenshot.png + +Claude: +1. Runs: npx -y bun ./scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png +2. Chrome opens with X compose page +3. Text is typed into editor +4. Image is copied to clipboard and pasted +5. Browser stays open 30s for preview +6. Reports: "Post composed. Use --submit to post." +``` + +## Troubleshooting + +- **Chrome not found**: Set `X_BROWSER_CHROME_PATH` environment variable +- **Not logged in**: First run opens Chrome - log in manually, cookies are saved +- **Image paste fails**: Verify clipboard script: `npx -y bun ./scripts/copy-to-clipboard.ts image ` +- **Rate limited**: Wait a few minutes before retrying + +## How It Works + +The `x-browser.ts` script uses Chrome DevTools Protocol (CDP) to: +1. Launch real Chrome (not Playwright) with `--disable-blink-features=AutomationControlled` +2. Use persistent profile directory for saved login sessions +3. Interact with X via CDP commands (Runtime.evaluate, Input.dispatchKeyEvent) +4. Paste images from system clipboard + +This approach bypasses X's anti-automation detection that blocks Playwright/Puppeteer. + +## Notes + +- First run requires manual login (session is saved) +- Always preview before using `--submit` +- Browser closes automatically after operation +- Supports macOS, Linux, and Windows + +--- + +# X Articles (Long-form Publishing) + +Publish Markdown articles to X Articles editor with rich text formatting and images. + +## X Article Usage + +```bash +# Publish markdown article (preview mode) +/post-to-x article /path/to/article.md + +# With custom cover image +/post-to-x article article.md --cover ./hero.png + +# With custom title +/post-to-x article article.md --title "My Custom Title" + +# Actually publish (not just draft) +/post-to-x article article.md --submit +``` + +## Prerequisites for Articles + +- X Premium subscription (required for Articles) +- Google Chrome installed +- `bun` installed + +## Article Script + +Use `x-article.ts` directly: + +```bash +npx -y bun ./scripts/x-article.ts article.md +npx -y bun ./scripts/x-article.ts article.md --cover ./cover.jpg +npx -y bun ./scripts/x-article.ts article.md --submit +``` + +## Markdown Format + +```markdown +--- +title: My Article Title +cover_image: /path/to/cover.jpg +--- + +# Title (becomes article title) + +Regular paragraph text with **bold** and *italic*. + +## Section Header + +More content here. + +![Image alt text](./image.png) + +- List item 1 +- List item 2 + +1. Numbered item +2. Another item + +> Blockquote text + +[Link text](https://example.com) + +\`\`\` +Code blocks become blockquotes (X doesn't support code) +\`\`\` +``` + +## Frontmatter Fields + +| Field | Description | +|-------|-------------| +| `title` | Article title (or uses first H1) | +| `cover_image` | Cover image path or URL | +| `cover` | Alias for cover_image | +| `image` | Alias for cover_image | + +## Image Handling + +1. **Cover Image**: First image or `cover_image` from frontmatter +2. **Remote Images**: Automatically downloaded to temp directory +3. **Placeholders**: Images in content use `[[IMAGE_PLACEHOLDER_N]]` format +4. **Insertion**: Placeholders are found, selected, and replaced with actual images + +## Markdown to HTML Script + +Convert markdown and inspect structure: + +```bash +# Get JSON with all metadata +npx -y bun ./scripts/md-to-html.ts article.md + +# Output HTML only +npx -y bun ./scripts/md-to-html.ts article.md --html-only + +# Save HTML to file +npx -y bun ./scripts/md-to-html.ts article.md --save-html /tmp/article.html +``` + +JSON output: +```json +{ + "title": "Article Title", + "coverImage": "/path/to/cover.jpg", + "contentImages": [ + { + "placeholder": "[[IMAGE_PLACEHOLDER_1]]", + "localPath": "/tmp/x-article-images/img.png", + "blockIndex": 5 + } + ], + "html": "

Content...

", + "totalBlocks": 20 +} +``` + +## Supported Formatting + +| Markdown | HTML Output | +|----------|-------------| +| `# H1` | Title only (not in body) | +| `## H2` - `###### H6` | `

` | +| `**bold**` | `` | +| `*italic*` | `` | +| `[text](url)` | `` | +| `> quote` | `
` | +| `` `code` `` | `` | +| ```` ``` ```` | `
` (X limitation) | +| `- item` | `