13 KiB
X Articles - Detailed Guide
Publish Markdown articles to X Articles editor with rich text formatting and images.
Mode Selection
In Codex, choose the browser-control mode from the user's wording:
- If the user says "Codex Chrome plugin", "Codex 自带的 Chrome 插件",
@chrome, or Chrome Extension, use Codex Chrome Plugin Workflow. Do not try Computer Use first. - If the user explicitly asks for Chrome Computer Use, use Computer Use Workflow.
- If the user explicitly asks for CDP/script mode, use CDP Script Workflow.
- Otherwise, use Computer Use when available; if unavailable or blocked, use CDP Script Workflow.
Never use the in-app Browser for X Article publishing. Never switch away from an explicitly requested mode without explaining the blocker and getting approval.
Prerequisites
- X Premium subscription (required for Articles)
- Google Chrome installed
buninstalled
Usage
Codex Chrome Plugin (When Requested)
Use the chrome:Chrome skill and its Node REPL browser client. Verify the connection with a lightweight call such as browser.user.openTabs(). If it fails, wait 2 seconds and retry once, then follow the Chrome skill's health checks.
Prepare the article HTML and image map:
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md --save-html /tmp/x-article-body.html > /tmp/x-article.json
Copy generated HTML as rich text:
${BUN_X} {baseDir}/scripts/copy-to-clipboard.ts html --file /tmp/x-article-body.html
Use the Chrome plugin's tab, Playwright-wrapper, CUA, clipboard, and file chooser APIs for all X UI operations. If upload fails with Not allowed, stop and tell the user to enable file URL access for the Codex Chrome Extension in chrome://extensions → Details.
Chrome Computer Use
Prepare the article HTML and image map:
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md --save-html /tmp/x-article-body.html > /tmp/x-article.json
Copy the generated HTML as rich text:
${BUN_X} {baseDir}/scripts/copy-to-clipboard.ts html --file /tmp/x-article-body.html
Then use Codex Computer Use against Google Chrome for all X UI operations.
CDP Script Fallback
# Publish markdown article (preview mode)
${BUN_X} {baseDir}/scripts/x-article.ts article.md
# With custom cover image
${BUN_X} {baseDir}/scripts/x-article.ts article.md --cover ./cover.jpg
# Actually publish
${BUN_X} {baseDir}/scripts/x-article.ts article.md --submit
Do not use --submit unless the user has explicitly confirmed the final public publish action.
Markdown Format
---
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.

- 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
- Cover Image: First image or
cover_imagefrom frontmatter - Remote Images: Automatically downloaded to temp directory
- Placeholders: Images in content use
XIMGPH_Nformat - Insertion: Placeholders are found, selected, and replaced with actual images
Markdown to HTML Script
Convert markdown and inspect structure:
# Get JSON with all metadata
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md
# Output HTML only
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md --html-only
# Save HTML to file
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md --save-html /tmp/article.html
JSON output:
{
"title": "Article Title",
"coverImage": "/path/to/cover.jpg",
"contentImages": [
{
"placeholder": "XIMGPH_1",
"localPath": "/tmp/x-article-images/img.png",
"blockIndex": 5
}
],
"html": "<p>Content...</p>",
"totalBlocks": 20
}
Supported Formatting
| Markdown | HTML Output |
|---|---|
# H1 |
Title only (not in body) |
## H2 - ###### H6 |
<h2> |
**bold** |
<strong> |
*italic* |
<em> |
[text](url) |
<a href> |
> quote |
<blockquote> |
`code` |
<code> |
``` |
<blockquote> (X limitation) |
- item |
<ul><li> |
1. item |
<ol><li> |
 |
Image placeholder |
Codex Chrome Plugin Workflow
- Load Chrome skill: use
chrome:Chrome, not Computer Use. - Connect: initialize the Chrome plugin browser client and verify with
browser.user.openTabs(). - Parse Markdown: run
md-to-html.ts --save-html /tmp/x-article-body.html > /tmp/x-article.json. - Read the map: use
/tmp/x-article.jsonfortitle,coverImage, andcontentImages. - Open X Articles: open or claim a Chrome tab for
https://x.com/compose/articles. - Create Draft: click the create/write button if needed, or open the target draft.
- Upload Cover: use the Chrome plugin file chooser flow. If file upload returns
Not allowed, report the Chrome Extension file-access fix and stop. - Fill Title: fill the title field.
- Paste Content:
- Run
copy-to-clipboard.ts html --file /tmp/x-article-body.html. - Click the article body.
- Press
Meta+Von macOS orControl+Von Windows/Linux through the Chrome plugin. - Verify the article body appeared and contains
XIMGPH_placeholders. On macOS, usepbpasteto verify shell-written system clipboard contents if paste is suspicious;tab.clipboard.readText()may not reflect the system clipboard after shell writes.
- Run
- Insert Images: for each
contentImagesitem in placeholder order:
- Locate the exact visible placeholder text (
XIMGPH_N) and click it to put the insertion point there. - Open the editor toolbar dropdown
Insertand chooseMedia. - In the
Insertmodal, click the icon button witharia-label="Add photos or video"; do not click the "Choose a file or drag it here" text/dropzone or hidden file input. - Use the Chrome plugin file chooser flow to upload that image's
localPath. - Wait until the image block appears. If
XIMGPH_Nremains above the image, select exactly that placeholder and pressDeletefirst; useBackspaceonly ifDeletefails and the selected text is confirmed to be exactly the placeholder. - Verify that placeholder's count is
0before continuing.
- Verify:
- Inspect the editor for
XIMGPH_residue. - Confirm the expected number of image blocks is visible.
- Open Preview and verify title, cover, body, links, and images.
- Publish Safety: ask the user for explicit final confirmation before clicking
Publish.
If the Chrome plugin reports native pipe is closed, retry one lightweight browser call after 2 seconds, then run the Chrome skill health checks. If Chrome, the extension, and native host are healthy, ask the user before opening a new Chrome window and retrying.
Computer Use Workflow
- Detect Computer Use: call
get_app_stateforGoogle Chrome; usetool_searchfirst if the tools are not visible. - Parse Markdown: run
md-to-html.ts --save-html /tmp/x-article-body.html > /tmp/x-article.json. - Read the map: use
/tmp/x-article.jsonfortitle,coverImage, andcontentImages. - Open X Articles: use Chrome Computer Use to navigate to
https://x.com/compose/articles. - Create Draft: click the create/write button if needed, or open the target draft.
- Upload Cover: if
coverImageexists, use Chrome's visible upload/file picker UI. If the file picker cannot be operated reliably, stop and ask for help rather than switching to CDP silently. - Fill Title: type the title into the title field.
- Paste Content:
- Run
copy-to-clipboard.ts html --file /tmp/x-article-body.html. - Click the article body.
- Press
super+von macOS orcontrol+von Windows/Linux with Computer Use.
- Run
- Insert Images: for each
contentImagesitem in placeholder order:- Locate the exact visible placeholder text (
XIMGPH_N) and click it to put the insertion point there. - Open the editor toolbar dropdown
Insert, chooseMedia, then click the icon button witharia-label="Add photos or video"inside the modal. - Use the native file picker to choose that image's
localPath. - Wait until the image block appears and upload activity is complete.
- If
XIMGPH_Nremains above the inserted image, reselect exactly that placeholder text and pressDeletefirst; useBackspaceonly ifDeletefails and the Computer Use state confirms the selected text is exactly the placeholder. - Confirm that placeholder is gone before continuing.
- Locate the exact visible placeholder text (
- Verify:
- Inspect the Computer Use state for
XIMGPH_residue. - Confirm the expected number of image blocks is visible.
- Open Preview and verify title, cover, body, links, and images.
- Publish Safety: ask the user for explicit final confirmation before clicking
Publish.
CDP Script Workflow (Fallback)
- Parse Markdown: Extract title, cover, content images, generate HTML
- Launch Chrome: Real browser with CDP, persistent login
- Navigate: Open
x.com/compose/articles - Create Article: Click create button if on list page
- Upload Cover: Use file input for cover image
- Fill Title: Type title into title field
- Paste Content: Copy HTML to clipboard, paste into editor
- Insert Images: For each placeholder in placeholder order:
- Find and click the placeholder text in the editor
- Use
Insert->Media - Click the modal's icon button labeled
Add photos or video - Upload the matching image file
- Delete the leftover placeholder text with
Deleteafter the image appears
- Post-Composition Check (automatic):
- Scan editor for remaining
XIMGPH_placeholders - Compare expected vs actual image count
- Warn if issues found
- Scan editor for remaining
- Review: Browser stays open for 60s preview
- Publish: Only with
--submitflag and explicit user confirmation
Example Session
User: /post-to-x article ./blog/my-post.md --cover ./thumbnail.png
Claude:
1. Detects that the user requested the Codex Chrome plugin
2. Parses markdown: title="My Post", 3 content images
3. Saves `/tmp/x-article-body.html` and `/tmp/x-article.json`
4. Uses the Chrome plugin to open X Articles and create a draft
5. Uploads thumbnail.png as cover
6. Fills title "My Post"
7. Pastes HTML content with a real Chrome paste
8. Inserts 3 images at placeholder positions
9. Opens Preview and asks before publishing
Troubleshooting
- No create button: Ensure X Premium subscription is active
- Cover upload fails: Check file path and format (PNG, JPEG)
- Images not inserting: Verify placeholders exist in pasted content; use
Insert->Media-> modal icon buttonAdd photos or video, not image clipboard paste, the dropzone text, or the hidden file input. - Content not pasting: Check HTML clipboard:
${BUN_X} {baseDir}/scripts/copy-to-clipboard.ts html --file /tmp/test.html - Chrome plugin
native pipe is closed: retry once after 2 seconds, then run Chrome skill checks; ask before opening a new Chrome window if checks pass. - Chrome plugin upload
Not allowed: enable file URL access for the Codex Chrome Extension inchrome://extensions→ Details. - Computer Use unavailable: Use the CDP fallback script, unless the user explicitly required Chrome Computer Use.
- Placeholder remains after upload: Select only the placeholder text and press
Deleteafter upload completes. UseBackspaceonly ifDeletefails and the selection is exactly the placeholder.
How It Works
-
md-to-html.tsconverts Markdown to HTML:- Extracts frontmatter (title, cover)
- Converts markdown to HTML
- Replaces images with unique placeholders
- Downloads remote images locally
- Returns structured JSON
-
The Codex Chrome plugin publishes through the user's real Chrome session when explicitly requested:
- Uses the user's active Chrome profile and logged-in X session
- Uses the Chrome Extension browser client rather than Computer Use or CDP
- Uses
copy-to-clipboard.tsfor rich HTML body paste - Inserts body images through X's toolbar
Insert->Mediamodal and itsAdd photos or videoicon button - Keeps the final publish click under user confirmation
-
Chrome Computer Use publishes through the user's visible Chrome UI:
- Uses the user's active Chrome profile and logged-in X session
- Uses
copy-to-clipboard.tsfor rich HTML body paste - Inserts body images through X's toolbar
Insert->Mediamodal and itsAdd photos or videoicon button - Uses real keystrokes (
super+v/control+v) through Codex Computer Use - Keeps the final publish click under user confirmation
-
x-article.tspublishes via CDP as a fallback:- Launches real Chrome (bypasses detection)
- Uses persistent profile (saved login)
- Navigates and fills editor via DOM manipulation
- Pastes HTML from system clipboard
- Finds/selects/replaces each image placeholder