This guide demonstrates how to automate publishing rich-text articles to X (Twitter) using agent-browser, Python, and the MacOS clipboard. It bypasses X's lack of an API for long-form articles by automating the web editor.
- Parse Markdown: Extract title, cover image, and convert body to HTML.
- Browser Automation: Open X editor, upload cover, and fill title.
- Rich Text Paste: Use Python to put HTML on the system clipboard as rich text, then paste (
Cmd+V) into the browser. - Inline Images: Copy images to clipboard and paste them at specific insertion points.
Save as copy_to_clipboard.py. Requires pyobjc-framework-Cocoa.
import argparse
import sys
from AppKit import NSPasteboard, NSPasteboardTypeHTML, NSPasteboardTypeString
from Foundation import NSData
def copy_html_macos(html):
pasteboard = NSPasteboard.generalPasteboard()
pasteboard.clearContents()
# Set HTML content for rich text paste
html_data = html.encode('utf-8')
ns_data = NSData.dataWithBytes_length_(html_data, len(html_data))
pasteboard.setData_forType_(ns_data, NSPasteboardTypeHTML)
# Fallback plain text
pasteboard.setString_forType_(html, NSPasteboardTypeString)
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('content', nargs='?')
args = parser.parse_args()
# Read from stdin if no argument
content = args.content if args.content else sys.stdin.read()
copy_html_macos(content)Save as copy_image.py. Requires Pillow and pyobjc-framework-Cocoa.
import sys
import io
from PIL import Image
from AppKit import NSPasteboard, NSPasteboardTypeTIFF
from Foundation import NSData
def copy_image(path):
img = Image.open(path)
buffer = io.BytesIO()
img.save(buffer, format='TIFF')
data = buffer.getvalue()
pasteboard = NSPasteboard.generalPasteboard()
pasteboard.clearContents()
ns_data = NSData.dataWithBytes_length_(data, len(data))
pasteboard.setData_forType_(ns_data, NSPasteboardTypeTIFF)
if __name__ == "__main__":
copy_image(sys.argv[1])This script coordinates the entire process. It assumes you have Chrome open with remote debugging enabled (--remote-debugging-port=9222).
#!/bin/bash
# 1. Parse Markdown to HTML (using a parser script, or simple pandoc)
# python3 parse_markdown.py my_post.md > article.json
TITLE="My Awesome Article"
COVER_IMG="cover.png"
BODY_HTML="<h1>Hello World</h1><p>This is a test.</p>"
# 2. Connect to Chrome & Open Editor
agent-browser --cdp 9222 open https://x.com/compose/articles
agent-browser --cdp 9222 wait 5000
# 3. Create New Article
# Click the 'Create' button (ref may vary, snapshot to find it)
agent-browser --cdp 9222 click "button[aria-label='Create']"
# 4. Upload Cover Image & Set Title
agent-browser --cdp 9222 upload "input[type='file']" "$COVER_IMG"
agent-browser --cdp 9222 fill "textarea[placeholder='Title']" "$TITLE"
# 5. Paste Rich Text Body
# Copy HTML to clipboard using our helper
echo "$BODY_HTML" | python3 copy_to_clipboard.py
# Focus the editor body
agent-browser --cdp 9222 click "div[role='textbox']"
# Paste!
agent-browser --cdp 9222 press Meta+v
# 6. Insert Inline Image
# Copy image to clipboard
python3 copy_image.py "inline_graph.png"
# Navigate to insertion point (e.g., click a specific header)
agent-browser --cdp 9222 click "h2"
agent-browser --cdp 9222 press End # Move cursor to end of line
agent-browser --cdp 9222 press Enter # New line
agent-browser --cdp 9222 press Meta+v # Paste image- Chrome Debugging: You must start Chrome with:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 - Dependencies:
pip install pyobjc-framework-Cocoa Pillow - X Premium: Required to access the Articles feature.