home / skills / jimliu / baoyu-skills / baoyu-danger-x-to-markdown

baoyu-danger-x-to-markdown skill

/skills/baoyu-danger-x-to-markdown

This skill converts X tweets and articles to markdown with YAML front matter, after user consent verification and optional media handling.

npx playbooks add skill jimliu/baoyu-skills --skill baoyu-danger-x-to-markdown

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

Files (16)
SKILL.md
8.6 KB
---
name: baoyu-danger-x-to-markdown
description: Converts X (Twitter) tweets and articles to markdown with YAML front matter. Uses reverse-engineered API requiring user consent. Use when user mentions "X to markdown", "tweet to markdown", "save tweet", or provides x.com/twitter.com URLs for conversion.
---

# X to Markdown

Converts X content to markdown:
- Tweets/threads → Markdown with YAML front matter
- X Articles → Full content extraction

## Script Directory

Scripts located in `scripts/` subdirectory.

**Path Resolution**:
1. `SKILL_DIR` = this SKILL.md's directory
2. Script path = `${SKILL_DIR}/scripts/main.ts`

## Consent Requirement

**Before any conversion**, check and obtain consent.

### Consent Flow

**Step 1**: Check consent file

```bash
# macOS
cat ~/Library/Application\ Support/baoyu-skills/x-to-markdown/consent.json

# Linux
cat ~/.local/share/baoyu-skills/x-to-markdown/consent.json
```

**Step 2**: If `accepted: true` and `disclaimerVersion: "1.0"` → print warning and proceed:
```
Warning: Using reverse-engineered X API. Accepted on: <acceptedAt>
```

**Step 3**: If missing or version mismatch → display disclaimer:
```
DISCLAIMER

This tool uses a reverse-engineered X API, NOT official.

Risks:
- May break if X changes API
- No guarantees or support
- Possible account restrictions
- Use at your own risk

Accept terms and continue?
```

Use `AskUserQuestion` with options: "Yes, I accept" | "No, I decline"

**Step 4**: On accept → create consent file:
```json
{
  "version": 1,
  "accepted": true,
  "acceptedAt": "<ISO timestamp>",
  "disclaimerVersion": "1.0"
}
```

**Step 5**: On decline → output "User declined. Exiting." and stop.

## Preferences (EXTEND.md)

Use Bash to check EXTEND.md existence (priority order):

```bash
# Check project-level first
test -f .baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md && echo "project"

# Then user-level (cross-platform: $HOME works on macOS/Linux/WSL)
test -f "$HOME/.baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md" && echo "user"
```

┌────────────────────────────────────────────────────────────┬───────────────────┐
│                            Path                            │     Location      │
├────────────────────────────────────────────────────────────┼───────────────────┤
│ .baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md         │ Project directory │
├────────────────────────────────────────────────────────────┼───────────────────┤
│ $HOME/.baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md   │ User home         │
└────────────────────────────────────────────────────────────┴───────────────────┘

┌───────────┬───────────────────────────────────────────────────────────────────────────┐
│  Result   │                                  Action                                   │
├───────────┼───────────────────────────────────────────────────────────────────────────┤
│ Found     │ Read, parse, apply settings                                               │
├───────────┼───────────────────────────────────────────────────────────────────────────┤
│ Not found │ **MUST** run first-time setup (see below) — do NOT silently create defaults │
└───────────┴───────────────────────────────────────────────────────────────────────────┘

**EXTEND.md Supports**: Download media by default | Default output directory

### First-Time Setup (BLOCKING)

**CRITICAL**: When EXTEND.md is not found, you **MUST use `AskUserQuestion`** to ask the user for their preferences before creating EXTEND.md. **NEVER** create EXTEND.md with defaults without asking. This is a **BLOCKING** operation — do NOT proceed with any conversion until setup is complete.

Use `AskUserQuestion` with ALL questions in ONE call:

**Question 1** — header: "Media", question: "How to handle images and videos in tweets?"
- "Ask each time (Recommended)" — After saving markdown, ask whether to download media
- "Always download" — Always download media to local imgs/ and videos/ directories
- "Never download" — Keep original remote URLs in markdown

**Question 2** — header: "Output", question: "Default output directory?"
- "x-to-markdown (Recommended)" — Save to ./x-to-markdown/{username}/{tweet-id}.md
- (User may choose "Other" to type a custom path)

**Question 3** — header: "Save", question: "Where to save preferences?"
- "User (Recommended)" — ~/.baoyu-skills/ (all projects)
- "Project" — .baoyu-skills/ (this project only)

After user answers, create EXTEND.md at the chosen location, confirm "Preferences saved to [path]", then continue.

Full reference: [references/config/first-time-setup.md](references/config/first-time-setup.md)

### Supported Keys

| Key | Default | Values | Description |
|-----|---------|--------|-------------|
| `download_media` | `ask` | `ask` / `1` / `0` | `ask` = prompt each time, `1` = always download, `0` = never |
| `default_output_dir` | empty | path or empty | Default output directory (empty = `./x-to-markdown/`) |

**Value priority**:
1. CLI arguments (`--download-media`, `-o`)
2. EXTEND.md
3. Skill defaults

## Usage

```bash
npx -y bun ${SKILL_DIR}/scripts/main.ts <url>
npx -y bun ${SKILL_DIR}/scripts/main.ts <url> -o output.md
npx -y bun ${SKILL_DIR}/scripts/main.ts <url> --download-media
npx -y bun ${SKILL_DIR}/scripts/main.ts <url> --json
```

## Options

| Option | Description |
|--------|-------------|
| `<url>` | Tweet or article URL |
| `-o <path>` | Output path |
| `--json` | JSON output |
| `--download-media` | Download image/video assets to local `imgs/` and `videos/`, and rewrite markdown links to local relative paths |
| `--login` | Refresh cookies only |

## Supported URLs

- `https://x.com/<user>/status/<id>`
- `https://twitter.com/<user>/status/<id>`
- `https://x.com/i/article/<id>`

## Output

```markdown
---
url: "https://x.com/user/status/123"
author: "Name (@user)"
tweetCount: 3
coverImage: "https://pbs.twimg.com/media/example.jpg"
---

Content...
```

**File structure**: `x-to-markdown/{username}/{tweet-id}.md`

When `--download-media` is enabled:
- Images are saved to `imgs/` next to the markdown file
- Videos are saved to `videos/` next to the markdown file
- Markdown media links are rewritten to local relative paths

## Media Download Workflow

Based on `download_media` setting in EXTEND.md:

| Setting | Behavior |
|---------|----------|
| `1` (always) | Run script with `--download-media` flag |
| `0` (never) | Run script without `--download-media` flag |
| `ask` (default) | Follow the ask-each-time flow below |

### Ask-Each-Time Flow

1. Run script **without** `--download-media` → markdown saved
2. Check saved markdown for remote media URLs (`https://` in image/video links)
3. **If no remote media found** → done, no prompt needed
4. **If remote media found** → use `AskUserQuestion`:
   - header: "Media", question: "Download N images/videos to local files?"
   - "Yes" — Download to local directories
   - "No" — Keep remote URLs
5. If user confirms → run script **again** with `--download-media` (overwrites markdown with localized links)

## Authentication

1. **Environment variables** (preferred): `X_AUTH_TOKEN`, `X_CT0`
2. **Chrome login** (fallback): Auto-opens Chrome, caches cookies locally

## Extension Support

Custom configurations via EXTEND.md. See **Preferences** section for paths and supported options.

Overview

This skill converts X (Twitter) tweets, threads, and X Articles into clean Markdown files with YAML front matter. It extracts full article content or tweet threads, embeds metadata (author, url, coverImage, tweetCount), and can optionally download media into local imgs/ and videos/ folders. The tool requires explicit user consent because it uses a reverse-engineered X API.

How this skill works

Provide an X or Twitter URL and the script fetches the content, builds a Markdown document with YAML front matter, and writes the file to the chosen output directory. On first run it enforces a consent and preferences flow: users must accept a disclaimer for the reverse-engineered API and complete a blocking setup that defines media handling and output location. Media download is configurable and can be done automatically or after an interactive prompt.

When to use it

  • You want to archive a tweet, thread, or X Article as Markdown with metadata for note-taking or publishing.
  • You need consistent filename and folder structure like x-to-markdown/{username}/{tweet-id}.md.
  • You want local copies of images/videos alongside converted markdown files.
  • You need machine-readable output (YAML front matter) for static site generators or personal knowledge bases.
  • You prefer CLI batch conversion with options for JSON output and download controls.

Best practices

  • Always read and accept the disclaimer before using the tool — consent is required and tracked in a local consent file.
  • Complete the first-time setup (EXTEND.md) interactively to choose media behavior and output directory; do not skip or create defaults silently.
  • Prefer environment-variable authentication (X_AUTH_TOKEN, X_CT0) to avoid automating a browser login.
  • Use the --download-media flag or the interactive media prompt when you need local assets; keep remote URLs otherwise to save space.
  • Store EXTEND.md in your preferred scope (user or project) to keep consistent behavior across runs.

Example use cases

  • Save a long tweet thread as a single Markdown document with author and tweetCount metadata.
  • Convert an X Article into full Markdown for editing or publishing in a personal blog.
  • Archive media-heavy tweets and download images/videos to imgs/ and videos/ for offline access.
  • Integrate Markdown output into a static site generator by using the YAML front matter fields.
  • Batch-convert shared tweet links from research notes into a structured folder for later review.

FAQ

Is user consent required?

Yes. You must accept a disclaimer before any conversion; consent is stored locally and checked on subsequent runs.

Where are preferences saved?

Preferences are saved to EXTEND.md either in the project (.baoyu-skills/) or the user home (~/.baoyu-skills/) depending on your choice during setup.

How are media files handled?

Media behavior follows EXTEND.md settings: always download, never download, or ask each time. Downloaded media are saved next to the markdown file in imgs/ and videos/ and links are rewritten to local paths.