npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

x-to-markdown

v0.1.0

Published

Claude and Codex skill to convert X/Twitter posts, threads, and X Articles into Markdown using the official X API v2.

Readme

X/Twitter to Markdown

A Claude Code and OpenAI Codex agent skill that converts X/Twitter posts, threads, and long-form X Articles into clean Markdown files with YAML frontmatter.

Use it to archive tweets, save X Articles to Obsidian or other PKM systems, preserve research threads, and feed social posts into AI workflows. It uses the official X API v2 with your own Bearer token: no scraping, no browser cookies, no account session, no telemetry, and no third-party extraction service.

$ bun scripts/main.ts https://x.com/jack/status/20
[x-to-markdown] Fetching tweet 20 (cost: $0.005, URL input)...
[x-to-markdown] Wrote ./x-to-markdown/jack/20.md

Features

  • Posts, threads, and X Articles — auto-detected from a single URL.
  • YAML frontmatter with author, source URL, cover image, timestamps.
  • Optional media download — images and videos saved alongside the markdown, with a hostname allowlist (pbs.twimg.com, video.twimg.com), 100 MB cap, 30 s timeout, and redirect: "manual" for SSRF resistance.
  • Cost-aware — URL inputs skip the User resource expansion ($0.005/article); bare-ID inputs pay full price ($0.015) for display-name resolution.
  • No telemetry, no third-party hosts, no credentials persisted to disk.

Why this instead of scraping-based Twitter/X readers?

  • Uses the official X API v2.
  • Does not read browser cookies.
  • Does not touch your logged-in account session.
  • Does not send content to third-party extraction services.
  • Writes local Markdown with YAML frontmatter.
  • Includes a documented output threat model for untrusted social content.

Install

No-clone skill install

After the npm package is published, install the skill into Claude Code, Codex, Cursor, or all three without cloning the repo:

npx x-to-markdown install --platform claude
npx x-to-markdown install --platform codex
npx x-to-markdown install --platform cursor
npx x-to-markdown install --platform all

Use --force to replace an existing installed copy:

npx x-to-markdown install --platform all --force

The installer writes the skill to user-level agent skill directories:

| Platform | Destination | |---|---| | Claude Code | ~/.claude/skills/x-to-markdown | | OpenAI Codex | ~/.agents/skills/x-to-markdown | | Cursor | ~/.cursor/skills/x-to-markdown |

Claude Code plugin marketplace

After this repo is registered as a Claude Code marketplace, install the namespaced plugin skill:

/plugin marketplace add heyjello/x-to-markdown
/plugin install x-to-markdown@x-to-markdown

The skill is then available as /x-to-markdown:x-to-markdown.

OpenAI Codex plugin marketplace

Register this repo as a Codex marketplace:

codex plugin marketplace add heyjello/x-to-markdown

Then open the plugin browser and install x-to-markdown:

/plugins

Cursor GitHub import or plugin

Cursor can import agent skills from GitHub repository links:

  1. Open Cursor Settings -> Rules.
  2. In Project Rules, choose Add Rule.
  3. Select Remote Rule (Github).
  4. Enter https://github.com/heyjello/x-to-markdown.

This repo also includes .cursor-plugin/plugin.json so it can be submitted to the Cursor plugin marketplace or imported into a team marketplace.

Direct clone fallback

If you want a local editable copy instead of a package or marketplace install:

git clone https://github.com/heyjello/x-to-markdown ~/.agents/skills/x-to-markdown

Standalone CLI

After the npm package is published, run the converter without cloning:

npx x-to-markdown <url>

The converter itself runs on Bun. If you prefer a local checkout:

git clone https://github.com/heyjello/x-to-markdown
cd x-to-markdown
bun scripts/main.ts <url>

The scripts are TypeScript and run directly under Bun. Node 20+ users will need tsx or a build step for the converter; the install subcommand is Node-based.

Common uses

  • Convert a tweet to Markdown.
  • Convert a Twitter/X thread to Markdown.
  • Save a long-form X Article to Markdown.
  • Archive X posts for Obsidian, Logseq, or another PKM workflow.
  • Create clean source notes for research, content curation, or AI-agent context.

Setup

Get a Bearer token at https://console.x.com. The X API v2 is pay-per-request:

| Input shape | Cost per call | Why | |---|---|---| | https://x.com/<user>/status/<id> | $0.005 | Username extracted from URL; no User resource fetched. | | Bare numeric ID (e.g. 1234567890) | $0.015 | Full User expansion required for display name. |

export X_BEARER_TOKEN="AAAA..."

Usage

x-to-markdown <url> [options]

Options:

  • --output <path> / -o — output path (file or dir). Default: ./x-to-markdown/<username>/<id>.md
  • --thread — also fetch the reply chain. Uses search/recent, so threads older than 7 days fall back to the root tweet only (a Pro-tier API limitation).
  • --download-media — save images/videos under imgs/ and videos/ next to the markdown.
  • --json — emit JSON metadata to stdout instead of markdown.
  • --help / -h

Examples

# Single tweet
bun scripts/main.ts https://x.com/jack/status/20

# Thread with local media
bun scripts/main.ts https://x.com/elonmusk/status/... --thread --download-media -o ./out/

# Bare ID (costs $0.015)
bun scripts/main.ts 1234567890123456789

# JSON metadata for piping
bun scripts/main.ts https://x.com/jack/status/20 --json | jq -r '.markdownPath'

What it does NOT do

  • Article media URLs — v2 returns media keys for articles but does not expand them to URLs. The Media section lists keys with a note pointing back to the source tweet.
  • Threads older than 7 days — search/recent is 7-day-bound on the standard tier. The root tweet is fetched and a warning is logged.
  • Quoted-tweet author resolution on URL inputs — when the cost-saving URL path is used, the User resource isn't fetched, so quoted-tweet author display names aren't resolved. Articles don't surface this; tweets render the quoted block without the author parenthetical.

Output threat model

This output contains attacker-controlled content from public X posts. Treat it as untrusted text:

  • Safe with strict markdown renderers — no raw-HTML pass-through, no javascript: URL allowlist. The skill escapes HTML metacharacters, markdown control chars ( , [, ], (, ), `), and emits YAML frontmatter via JSON-string encoding.
  • Code-block fences auto-extend when content contains triple backticks.
  • Not safe to render with --unsafe markdown engines (e.g., GFM raw-HTML, marked w/ sanitize: false, MDX with HTML pass-through).
  • Not safe to pipe into an LLM that acts on instructions in content (out-of-scope: prompt injection).
  • Not safe to use as the source of truth for filenames, paths, or shell args without further validation.

Security

The Bearer token is read from X_BEARER_TOKEN once per invocation and never logged or written to disk. The only outbound hosts are api.x.com and (with --download-media) pbs.twimg.com / video.twimg.com.

Security posture:

  • Official X API v2 Bearer token only — no scraping, no session cookies, no account-suspension risk.
  • Media downloader hardened with hostname allowlist (pbs.twimg.com, video.twimg.com), manual redirect handling, response-size cap, and per-request timeout.
  • No credential persistence to disk.
  • No telemetry or third-party network calls.

To report a vulnerability, see SECURITY.md.

Runtime

Default: Bun. Node 20+ also works, but on machines with corporate TLS interception (e.g., Cisco Secure Access) you may need NODE_EXTRA_CA_CERTS pointing at the corporate CA bundle. Bun honors the system keychain on macOS and avoids this entirely.

Suggested GitHub topics

claude-skill, codex-skill, agent-skills, ai-agent, twitter, x-api, x-api-v2, x-articles, markdown, obsidian, pkm, content-archiving, typescript, bun, claude-code, openai-codex

License

MIT — see LICENSE.