{
  "markdown": "<div align=\"center\">      \n  \n<pre align=\"center\"> \n██╗  ██╗ █████╗  ██████╗████████╗██╗ ██████╗ ███╗   ██╗███████╗\n╚██╗██╔╝██╔══██╗██╔════╝╚══██╔══╝██║██╔═══██╗████╗  ██║██╔════╝\n ╚███╔╝ ███████║██║        ██║   ██║██║   ██║██╔██╗ ██║███████╗\n ██╔██╗ ██╔══██║██║        ██║   ██║██║   ██║██║╚██╗██║╚════██║\n██╔╝ ██╗██║  ██║╚██████╗   ██║   ██║╚██████╔╝██║ ╚████║███████║\n╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝   ╚═╝   ╚═╝ ╚═════╝ ╚═╝  ╚═══╝╚══════╝\n</pre>\n\n<p>\n  <img src=\".github/xactions-ascii.svg\" alt=\"XActions, the complete X/Twitter automation toolkit\" width=\"720\">\n</p>\n\n<h3>The complete X/Twitter automation toolkit</h3>\n\n<p>\nScrapers &nbsp;·&nbsp; MCP Server for AI Agents &nbsp;·&nbsp; CLI &nbsp;·&nbsp; Browser Scripts &nbsp;·&nbsp; Browser Extension<br>\n<strong>No API keys. No monthly fees. 100% open source.</strong>\n</p>\n\n<p>\n  <a href=\"https://www.npmjs.com/package/xactions\"><img src=\"https://img.shields.io/npm/v/xactions.svg?style=flat-square&color=cb3837&label=npm\" alt=\"npm version\"></a>&nbsp;\n  <a href=\"https://www.npmjs.com/package/xactions\"><img src=\"https://img.shields.io/npm/dm/xactions.svg?style=flat-square&color=cb3837&label=downloads\" alt=\"npm downloads\"></a>&nbsp;\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/license-Apache_2.0-green?style=flat-square\" alt=\"Apache 2.0 License\"></a>&nbsp;\n  <a href=\"https://github.com/nirholas/xactions\"><img src=\"https://img.shields.io/github/stars/nirholas/xactions?style=flat-square&color=f5c542&label=stars\" alt=\"Stars\"></a>\n</p>\n\n<p>\n  <a href=\"docs/mcp-setup.md\"><img src=\"https://img.shields.io/badge/MCP_Tools-152-8B5CF6?style=flat-square&logo=data:image/svg+xml;base64,PHN2Zz48L3N2Zz4=\" alt=\"153 MCP Tools\"></a>&nbsp;\n  <a href=\"https://smithery.ai/server/xactions\"><img src=\"https://smithery.ai/badge/xactions\" alt=\"Smithery\"></a>&nbsp;\n  <a href=\"https://registry.modelcontextprotocol.io\"><img src=\"https://img.shields.io/badge/MCP_Registry-deployed-6366f1?style=flat-square&logo=data:image/svg+xml;base64,PHN2Zz48L3N2Zz4=\" alt=\"MCP Registry\"></a>&nbsp;\n  <a href=\"Dockerfile\"><img src=\"https://img.shields.io/badge/Docker-ready-2496ED?style=flat-square&logo=docker&logoColor=white\" alt=\"Docker\"></a>&nbsp;\n  <a href=\"types/index.d.ts\"><img src=\"https://img.shields.io/badge/TypeScript-types_included-3178C6?style=flat-square&logo=typescript&logoColor=white\" alt=\"TypeScript\"></a>\n</p>\n\n<p>\n  <a href=\"https://x.com/nichxbt\"><img src=\"https://img.shields.io/badge/follow-@nichxbt-000000?style=flat-square&logo=x&logoColor=white\" alt=\"Follow @nichxbt\"></a>&nbsp;\n  <a href=\"https://x.ai\"><img src=\"https://img.shields.io/badge/built_with-Grok_🤖-1DA1F2?style=flat-square\" alt=\"Built with Grok\"></a>\n</p>\n\n  https://xactions.app\n\n<br>\n\n[**Website**](https://xactions.app) &nbsp;·&nbsp; [**npm**](https://www.npmjs.com/package/xactions) &nbsp;·&nbsp; [**Docs**](docs/getting-started.md) &nbsp;·&nbsp; [**MCP Server**](docs/mcp-setup.md) &nbsp;·&nbsp; [**Docker**](Dockerfile) &nbsp;·&nbsp; [**API Ref**](docs/api-reference.md)\n\n</div>\n\n---\n\n<div align=\"center\">\n\n### ⚡ Try it in 30 seconds\n\n</div>\n\n```bash\nnpx xactions profile nasa\n```\n\n```\n⚡ @NASA\n\n  Name:      NASA\n  Bio:       Making the seemingly impossible, possible. ✨\n  Location:  Pale Blue Dot\n  Website:   http://www.nasa.gov/\n  Joined:    2007-12-19\n  Following: 117  Followers: 92.4M\n  Tweets:    74.2K  Listed:    0\n  ✓ Verified\n```\n\nNo API key. No account. No browser. Real data in about a second.\n\n```bash\nnpx xactions tweets nasa --limit 100 --output nasa.csv   # timeline to a spreadsheet\nnpx xactions login                                        # unlock search, followers, DMs\nnpx xactions search \"your brand\" --limit 50               # what people are saying\n```\n\n<div align=\"center\">\n\n### ⚡ See it in action\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"public/demo.svg\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"public/demo.svg\">\n  <img alt=\"XActions CLI demo: profile lookup, tweet search, non-follower detection\" src=\"public/demo.svg\" width=\"720\">\n</picture>\n\n<video src=\"https://raw.githubusercontent.com/nirholas/XActions/main/public/demo.mp4\" controls width=\"720\"></video>\n\n</div>\n\n---\n\n## 🏆 How XActions Compares\n\n> Why build with XActions instead of the alternatives?\n\n| Feature | **XActions** | twikit | twscrape | x-use | xmcp (official) | bird | twitter-cli | Agent-Reach |\n|---------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\n| **No API Key Required** | ✅ | ✅ Cookies | ✅ Account pool | ✅ Browser | ❌ X API keys | ✅ Cookies | ❌ X API keys | ✅ |\n| **MCP Server (AI agents)** | ✅ **153 tools** | ❌ | ❌ | ✅ (33-tool server) | ✅ (140-tool, metered) | ❌ | ❌ | ❌ Skills, not MCP |\n| **Browser Console Scripts** | ✅ 95 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |\n| **AI Voice Agent in Spaces** | ✅ Join, listen, speak | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |\n| **CLI** | ✅ 56 commands | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ |\n| **Human approval gate on writes** | ✅ Every write held as a draft | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |\n| **Daily action caps that survive a restart** | ✅ Per account, on disk | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |\n| **Account pool with rotation** | ✅ SQLite, per-operation windows | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |\n| **Resumable long scrapes** | ✅ Cursor checkpoints | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |\n| **Cookies from your installed browser** | ✅ `--from-browser`, `--cookies-file` | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |\n| **Official X archive import** | ✅ `xactions archive` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |\n| **Language** | JavaScript | Python | Python | TypeScript | TypeScript | TypeScript | Python | Python |\n\n**XActions is the only toolkit that works in the browser, terminal, and with AI agents, all without an API key.**\n\nCompetitor columns come from the [competitive audit](docs/audits/2026-08-27-competitive-and-structural-audit.md), which names each project and what it does better than us. Where a rival led, we built it: the approval gate and the daily caps follow x-use, the account pool follows twscrape, cursor resume follows Scweet, and browser cookie import follows bird and twitter-cli.\n\n---\n\n## 🆕 What's New\n\n| Area | What changed |\n|------|-------------|\n| **Delete every reply you sent one account** | [`scripts/searchSweep.js`](scripts/searchSweep.js) turns any X search into a bulk action. Open `x.com/search?q=from:you @someone&f=live`, paste it, and delete, like, repost, or reply to every result, with a floating panel, a dry run, filters that protect posts that did numbers, and multiple passes because X search returns a slice at a time. Deletes only ever touch your own posts. [Docs](docs/search-sweep.md). |\n| **Sweep a whole profile** | [`scripts/engageProfile.js`](scripts/engageProfile.js) likes, reposts, and replies to every post on an account from the console, with a floating panel, dry run, resume, undo, and replies from your templates or from an LLM given a one-line brief (Grok works straight from the console; any provider through the extension). `xactions engage USERNAME --like --repost --comment --prompt \"...\"` does the same from the terminal with any provider. [Docs](docs/engage.md). |\n| **A CLI you can find your way around** | All 56 commands are now grouped by task instead of listed alphabetically. `xactions quickstart` gives a guided first run that adapts to what you already have set up. |\n| **Tab completion** | `xactions completion bash\\|zsh\\|fish` prints a completion script generated from the live command tree, so every command, sub-command, and flag completes. |\n| **Log in without touching DevTools** | `xactions login --from-browser` reads x.com cookies straight out of an installed Chrome, Chromium, Brave, Edge, Arc or Firefox profile. `--cookies-file` imports a Netscape `cookies.txt`, a Cookie-Editor or EditThisCookie JSON export, or a Playwright / Puppeteer `storageState`. A full cookie jar beats a bare `auth_token`, because it carries the `ct0` every write needs. |\n| **Query IDs that heal themselves** | X rotates its GraphQL query IDs and every pinned client 404s at once. Ours are discovered from x.com's own bundles and cached, so a rotation is invisible. `xactions doctor` reports the cache age. |\n| **Requests signed like the real client** | Every GraphQL call carries an `x-client-transaction-id` header computed the way x.com's own web client computes it, so reads get the answer the browser gets. |\n| **An account pool, and scrapes that resume** | Sessions live in a SQLite database with their own proxy and a per-operation rate-limit window read from X's own headers. The pooled client rotates on a 429 and locks an account on a 401. A checkpoint written after every page means a 50,000-follower scrape that dies at page 400 restarts from its cursor, not from page one. |\n| **Daily action caps** | Every MCP write is charged against a rolling 24 hour per-account budget stored on disk. The cap survives a restart, a crash, and a fresh `npx xactions-mcp`, and a call that would go over is refused before it reaches X. Defaults follow X's own published limits. |\n| **Writes a human releases** | `XACTIONS_MCP_REQUIRE_APPROVAL=1` turns every write tool into a draft. Review with `xactions drafts list`, release with `xactions drafts approve <id>`, or use the `x_list_drafts` / `x_approve_draft` / `x_discard_draft` tools. |\n| **MCP tool groups** | The tool list is filterable: `--tools read,analytics` or `XACTIONS_MCP_TOOLS=read` advertises only what the session needs, and a filtered tool is neither advertised nor callable. Groups: read, write, dm, lists, spaces, analytics, ai, grok, automation, monitoring, workflows, persona, graph, data, x402, drafts, auth. |\n| **MCP over HTTP** | `xactions-mcp --http` serves the Streamable HTTP transport on `/mcp` for remote and hosted clients, with optional bearer auth via `XACTIONS_MCP_TOKEN`. stdio is still the default. |\n| **One-drag install for Claude Desktop** | The `.mcpb` bundle carries the server and its dependencies and prompts for the session cookie and tool groups at install time, so nothing is typed into a config file. Attached to every release. |\n| **Skills you can install** | `xactions skills install --all` copies the 50 bundled skills into Claude Code, Cursor, Codex, Windsurf, or the current project. `xactions skills show <name>` reads one without installing it. |\n| **Bring your X archive** | `xactions archive summary\\|export\\|migrate` reads the official X data export zip: counts, date range, busiest year and top hashtags; a rewrite to JSON, CSV, Markdown and a browsable HTML viewer; or a migration to Bluesky or Mastodon. [Docs](docs/portability.md). |\n| **Live event streaming** | `src/streaming/livePipeline.js` reads x.com's own event pipeline: engagement counters, DM updates and typing indicators, pushed rather than polled, with subscriptions changed mid-session. It is a chunked newline-delimited JSON response, not a WebSocket, because x.com never answers that endpoint with a 101. |\n| **Signed webhooks** | Outbound deliveries carry an HMAC-SHA256 signature, a timestamp, an event type and a stable delivery id, retry three times with backoff, and land in a replayable delivery log. Receivers verify with the exported `verifyWebhookSignature`. |\n| **`--compact` and `--fields`** | Global on every read command. `--compact` prints one record per line as tab-separated `key=value` pairs with no colours or spinners; `--fields id,text,likes` narrows that to the columns you name. Built for agents and pipes. |\n| **`--json` everywhere** | Every read command accepts `--json` and puts data on stdout and nothing else. It outranks `--output`, so a pipe is never silently turned into a file write. |\n| **Reliability** | Public reads no longer need a browser at all. Profiles and timelines come from the internal GraphQL API in about a second, with no Chromium download. |\n| **Honest failures** | Nothing reports empty results as success anymore. A read that cannot complete says why, and says what to do about it. |\n| **Archive every photo and video** | `xactions download @nichxbt:all --archive` saves a profile's media, avatar and banner with gallery-dl-style filename templates, then re-runs incrementally. Resumes interrupted files with `Range`, retries rate limits, and hard-links the same photo reached through a retweet instead of storing it twice. Also `xactions/media` and the `x_download_media` MCP tool. [Docs](docs/media-archive.md). |\n| **Ask XActions** | [xactions.app/ask](https://xactions.app/ask) answers \"how do I...\" in plain language from these docs, the skills, the scripts and the repo, and ends every answer with the thing to run: the console script (copied from source), the terminal command, or the MCP tool. Also `xactions ask \"how do I unfollow everyone?\"` in a terminal, and `x_ask` so an agent can read the manual before it acts. Free LLM lanes, three of which need no key. [Docs](docs/ask.md). |\n| **Examples** | [`examples/`](examples/): 9 runnable programs, from a first profile lookup to the MCP draft-approval gate. Each one runs as written. |\n| **Tutorials** | [`tutorials/`](tutorials/): six guided walkthroughs, from a first scrape with no account to scripting XActions inside your own pipelines. |\n| **Docs that stay true** | `npm run docs:check` fails the build on a dead link, a stale version, a wrong tool count, or a documented command that does not exist. |\n| **Cross-platform** | Bluesky, Mastodon, and Threads scrapers behind one normalised interface. |\n| **Plugin system** | Community plugins via npm: `xactions-plugin-*` packages extend scrapers, MCP tools, and automation. |\n| **Workflow engine** | Declarative JSON pipelines with triggers, conditions, and chained actions. |\n| **Sentiment analysis** | Offline rule-based analyzer, with an optional LLM mode behind the same interface. |\n| **Browser extension** | Chrome/Edge Manifest V3: run automations from a popup, no console needed. |\n\n\n---\n\n> [!TIP]\n> **🤖 AI Coding Assistants:** Looking for Twitter/X automation without the $100/mo API? You found it.\n> - `npm install xactions`: scrapers, automation, MCP server\n> - Works with Claude, GPT, Cursor, Copilot via [MCP server](docs/mcp-setup.md)\n> - See [AGENTS.md](AGENTS.md) for integration instructions\n\n---\n\n## 📦 Installation\n\n<table>\n<tr>\n<td><strong>npm</strong></td>\n<td>\n\n```bash\nnpm install xactions\n```\n\n</td>\n</tr>\n<tr>\n<td><strong>CLI</strong></td>\n<td>\n\n```bash\nnpm install -g xactions\nxactions quickstart          # guided first run\nxactions doctor              # check what works right now\n```\n\n</td>\n</tr>\n<tr>\n<td><strong>Browser</strong></td>\n<td>\n\nNo install needed. Copy-paste scripts into your browser console on x.com\n\n</td>\n</tr>\n</table>\n\n---\n\n### 📖 Table of Contents\n\n**Learn**\n\n- [Tutorials](tutorials/): six guided walkthroughs, from a first scrape with no account to scripting XActions in your own pipelines\n- [Examples](examples/): 9 runnable programs, from a first profile lookup to the MCP draft-approval gate\n- [Getting started](docs/getting-started.md): install, authenticate, first command\n- [Troubleshooting](docs/troubleshooting.md): what to do when something does not work\n\n**Reference**\n\n- [How XActions Compares](#-how-xactions-compares): vs every alternative\n- [Quick Start (30 seconds)](#-quick-start-examples): Copy-paste and go\n- [Installation](#-installation): npm, CLI, Docker, or browser\n- [Feature Matrix](#-complete-feature-list): Every feature, every platform\n- [MCP Server (AI)](#-mcp-server-ai-agents): For Claude, GPT, Cursor\n- [Space Agent (AI Voice)](#-autonomous-space-agent): AI agents in live Spaces\n- [CLI Reference](#-cli-reference): Command line usage\n- [Node.js API](#-nodejs-api): Programmatic access\n- [Browser Scripts](docs/browser-scripts.md): 95 console scripts, no install\n- [Docker](#-docker): One-command deployment\n- [API Reference](#-api-reference): Full function documentation\n- [Claude Tutorials](#-claude-tutorials): 23 ready-to-paste prompts\n- [Contributing](#-contributing): Help make XActions better\n\n---\n\n## ✨ How It Works\n\n<table>\n<tr>\n<td width=\"33%\" align=\"center\"><strong>1. Paste</strong><br><br>Copy a script into the<br>x.com DevTools console</td>\n<td width=\"33%\" align=\"center\"><strong>2. Run</strong><br><br>Use the CLI, MCP server,<br>or browser extension</td>\n<td width=\"33%\" align=\"center\"><strong>3. Done</strong><br><br>Everything runs locally.<br>No data leaves your machine</td>\n</tr>\n</table>\n\n> Your x.com tab does all the work. Nothing gets scraped to our servers. **You're in control.**\n\n---\n\n## 💰 Pricing\n\n### 🆓 100% Free & Open Source\n\nEverything is **completely free**: browser scripts, CLI, Node.js library, MCP server, and API.\n\nNo API keys. No subscriptions. No paywalls. Just clone and run.\n\n<details>\n<summary>🤖 Optional: Remote API for AI Agents</summary>\n\nIf you self-host the XActions API for remote AI agent access, you can optionally enable pay-per-request micropayments via the [x402](https://x402.org) protocol. This is entirely optional and disabled by default.\n\n| Operation | Price |\n|-----------|-------|\n| Profile scrape | $0.001 |\n| Followers/Following | $0.01 |\n| Tweet scrape | $0.005 |\n| Search tweets | $0.01 |\n| Unfollow non-followers | $0.05 |\n| Detect unfollowers | $0.02 |\n| Auto-like | $0.02 |\n| Video download | $0.005 |\n\nThis only applies to the hosted remote API. Local mode is always free.\n\n</details>\n\n---\n\n## 🎯 Why XActions?\n\n<table>\n<tr>\n<td></td>\n<td align=\"center\"><strong>XActions</strong></td>\n<td align=\"center\"><strong>Others</strong></td>\n</tr>\n<tr><td><strong>Scope</strong></td><td>Browser + CLI + Node.js + MCP + Extension</td><td>Usually 1 thing</td></tr>\n<tr><td><strong>API Key</strong></td><td>Not needed</td><td>Most need Twitter API ($100/mo)</td></tr>\n<tr><td><strong>MCP Tools</strong></td><td>152 for Claude, GPT, Cursor</td><td>0-2 tools</td></tr>\n<tr><td><strong>AI Features</strong></td><td>Sentiment, Grok, reputation</td><td>None</td></tr>\n<tr><td><strong>Export</strong></td><td>JSON, CSV, Markdown, HTML</td><td>JSON only (if any)</td></tr>\n<tr><td><strong>Migration</strong></td><td>Bluesky and Mastodon, from a live account or an X archive zip</td><td>None</td></tr>\n<tr><td><strong>Tutorials</strong></td><td>23 Claude prompts</td><td>None</td></tr>\n</table>\n\n---\n\n## 🐳 Docker\n\nRun XActions anywhere with one command:\n\n```bash\n# Quick start\ndocker build -t xactions .\ndocker run -it xactions xactions profile elonmusk\n\n# Run the MCP server\ndocker run -p 3000:3000 xactions npm run mcp\n\n# With environment variables\ndocker run -e XACTIONS_SESSION_COOKIE=your_cookie xactions xactions followers elonmusk\n```\n\nOr use Docker Compose:\n\n```bash\ndocker compose up\n```\n\nSee [Dockerfile](Dockerfile) for details.\n\n---\n\n## 📖 API Reference\n\nFull TypeScript-compatible API with type declarations included.\n\n```typescript\nimport { createBrowser, createPage, scrapeProfile, scrapeFollowers } from 'xactions';\nimport { scrapeFollowing, scrapeTweets, searchTweets } from 'xactions/scrapers';\n```\n\n**Core Functions:**\n\n| Function | Description | Returns |\n|----------|-------------|---------|\n| `createBrowser(options?)` | Launch Puppeteer browser | `Browser` |\n| `createPage(browser)` | Create stealth page | `Page` |\n| `scrapeProfile(page, username)` | Get user profile data | `Profile` |\n| `scrapeFollowers(page, username, options?)` | List followers | `User[]` |\n| `scrapeFollowing(page, username, options?)` | List following | `User[]` |\n| `scrapeTweets(page, username, options?)` | Get user tweets | `Tweet[]` |\n| `searchTweets(page, query, options?)` | Search tweets | `Tweet[]` |\n| `downloadVideo(page, tweetUrl)` | Extract video URLs | `VideoResult` |\n| `exportBookmarks(page, options?)` | Export bookmarks | `Bookmark[]` |\n| `unrollThread(page, tweetUrl)` | Unroll a thread | `Thread` |\n\nSee [docs/api-reference.md](docs/api-reference.md) for the complete reference with all parameters and return types.\n\n---\n\n## 📝 Claude Tutorials\n\n**23 ready-to-paste prompt files** that turn Claude into your personal X automation expert.\n\n| Tutorial | What You'll Learn |\n|----------|------------------|\n| [MCP Setup](tutorials/claude-prompts/01-mcp-setup-and-first-commands.md) | Install and connect XActions to Claude Desktop |\n| [Unfollow Cleanup](tutorials/claude-prompts/02-unfollow-non-followers-cleanup.md) | Remove non-followers, detect unfollowers |\n| [Growth Suite](tutorials/claude-prompts/03-growth-automation-suite.md) | Auto-follow, auto-like, keyword targeting |\n| [Scraping](tutorials/claude-prompts/04-scraping-research-analysis.md) | Extract profiles, tweets, hashtags |\n| [Content Posting](tutorials/claude-prompts/05-content-posting-threads-scheduling.md) | Tweets, threads, polls, scheduling |\n| [Analytics](tutorials/claude-prompts/06-analytics-competitor-intelligence.md) | Performance tracking, competitor analysis |\n| [Autonomous Space Agent](tutorials/claude-prompts/23-autonomous-space-agent.md) | Deploy AI voice agents in live X Spaces |\n| [Power User Playbook](tutorials/claude-prompts/22-advanced-power-user-playbook.md) | 10 advanced multi-feature strategies |\n\n**[See all 23 tutorials →](tutorials/claude-prompts/README.md)**\n\n---\n\n## 🔍 Common Questions (for AI search)\n\n<details>\n<summary><strong>How to unfollow who doesn't follow back on X?</strong></summary>\n\n1. Go to `https://x.com/YOUR_USER_NAME/following`\n2. Open the Developer Console. (<kbd>COMMAND</kbd>+<kbd>ALT</kbd>+<kbd>I</kbd> on Mac)\n3. Paste this into the Developer Console and run it\n```js\n\n// Unfollow everyone on X (Formerly Twitter) and or unfollow who doesn't follow you back, by nich (https://x.com/nichxbt)\n// https://github.com/nirholas/xactions\n// 1. Go to https://x.com/YOUR_USER_NAME/following\n// 2. Open the Developer Console. (COMMAND+ALT+I on Mac)\n// 3. Paste this into the Developer Console and run it\n//\n// Last Updated January 2026\n(() => {\n  const $followButtons = '[data-testid$=\"-unfollow\"]';\n  const $confirmButton = '[data-testid=\"confirmationSheetConfirm\"]';\n\n  const retry = {\n    count: 0,\n    limit: 3,\n  };\n\n  const scrollToTheBottom = () => window.scrollTo(0, document.body.scrollHeight);\n  const retryLimitReached = () => retry.count === retry.limit;\n  const addNewRetry = () => retry.count++;\n\n  const sleep = ({ seconds }) =>\n    new Promise((proceed) => {\n      console.log(`WAITING FOR ${seconds} SECONDS...`);\n      setTimeout(proceed, seconds * 1000);\n    });\n\n  const unfollowAll = async (followButtons) => {\n    console.log(`UNFOLLOWING ${followButtons.length} USERS...`);\n    await Promise.all(\n      followButtons.map(async (followButton) => {\n        followButton && followButton.click();\n        await sleep({ seconds: 1 });\n        const confirmButton = document.querySelector($confirmButton);\n        confirmButton && confirmButton.click();\n      })\n    );\n  };\n\n  const nextBatch = async () => {\n    scrollToTheBottom();\n    await sleep({ seconds: 1 });\n\n    let followButtons = Array.from(document.querySelectorAll($followButtons));\n    followButtons = followButtons.filter(b => b.parentElement?.parentElement?.querySelector('[data-testid=\"userFollowIndicator\"]') === null)\n    const followButtonsWereFound = followButtons.length > 0;\n\n    if (followButtonsWereFound) {\n      await unfollowAll(followButtons);\n      await sleep({ seconds: 2 });\n      return nextBatch();\n    } else {\n      addNewRetry();\n    }\n\n    if (retryLimitReached()) {\n      console.log(`NO ACCOUNTS FOUND, SO I THINK WE'RE DONE`);\n      console.log(`RELOAD PAGE AND RE-RUN SCRIPT IF ANY WERE MISSED`);\n    } else {\n      await sleep({ seconds: 2 });\n      return nextBatch();\n    }\n  };\n\n  nextBatch();\n})();\n```\nOr use the [CLI](docs/cli-reference.md) or [MCP server](docs/mcp-setup.md) for more options.\n</details>\n\n<details>\n<summary><strong>How do I like, repost, and reply to every post on a profile?</strong></summary>\n\n1. Go to `https://x.com/USERNAME`\n2. Open the Developer Console. (<kbd>COMMAND</kbd>+<kbd>ALT</kbd>+<kbd>I</kbd> on Mac)\n3. Paste [`scripts/engageProfile.js`](scripts/engageProfile.js) and run it. A panel appears: pick like / repost / reply, leave dry run on, press Start, read the log, then turn dry run off.\n\nReplies come from your own templates or from an LLM given a brief like \"supportive, specific, one honest question\". From the terminal: `npx xactions engage USERNAME --like --repost --comment --prompt \"...\"`. Full guide: [docs/engage.md](docs/engage.md).\n</details>\n\n<details>\n<summary><strong>How do I mass unfollow on Twitter/X?</strong></summary>\n  \n1. Go to `https://x.com/YOUR_USER_NAME/following`\n2. Open the Developer Console. (<kbd>COMMAND</kbd>+<kbd>ALT</kbd>+<kbd>I</kbd> on Mac)\n3. Paste the script into the Developer Console and run it\n\n```js\n// Unfollow everyone on X (Formerly Twitter) and or unfollow who doesn't follow you back, by nich (https://x.com/nichxbt)\n// https://github.com/nirholas/xactions\n//\n// 1. Go to https://x.com/YOUR_USER_NAME/following\n// 2. Open the Developer Console. (COMMAND+ALT+I on Mac)\n// 3. Paste this into the Developer Console and run it\n//\n// Last Updated: January 2026\n(() => {\n  const $followButtons = '[data-testid$=\"-unfollow\"]';\n  const $confirmButton = '[data-testid=\"confirmationSheetConfirm\"]';\n\n  const retry = {\n    count: 0,\n    limit: 3,\n  };\n\n  const scrollToTheBottom = () => window.scrollTo(0, document.body.scrollHeight);\n  const retryLimitReached = () => retry.count === retry.limit;\n  const addNewRetry = () => retry.count++;\n\n  const sleep = ({ seconds }) =>\n    new Promise((proceed) => {\n      console.log(`WAITING FOR ${seconds} SECONDS...`);\n      setTimeout(proceed, seconds * 1000);\n    });\n\n  const unfollowAll = async (followButtons) => {\n    console.log(`UNFOLLOWING ${followButtons.length} USERS...`);\n    await Promise.all(\n      followButtons.map(async (followButton) => {\n        followButton && followButton.click();\n        await sleep({ seconds: 1 });\n        const confirmButton = document.querySelector($confirmButton);\n        confirmButton && confirmButton.click();\n      })\n    );\n  };\n\n  const nextBatch = async () => {\n    scrollToTheBottom();\n    await sleep({ seconds: 1 });\n\n    const followButtons = Array.from(document.querySelectorAll($followButtons));\n    const followButtonsWereFound = followButtons.length > 0;\n\n    if (followButtonsWereFound) {\n      await unfollowAll(followButtons);\n      await sleep({ seconds: 2 });\n      return nextBatch();\n    } else {\n      addNewRetry();\n    }\n\n    if (retryLimitReached()) {\n      console.log(`NO ACCOUNTS FOUND, SO I THINK WE'RE DONE`);\n      console.log(`RELOAD PAGE AND RE-RUN SCRIPT IF ANY WERE MISSED`);\n    } else {\n      await sleep({ seconds: 2 });\n      return nextBatch();\n    }\n  };\n\n  nextBatch();\n})();\n```\n\nThis script:\n\n- Is completely free.\n- Doesn't try and get you to sign in or take your personal data.\n- Automates your web browser to make it click unfollow buttons, scroll down to reveal more, then do it again.\n- No tricks, all of the code is here so you can see exactly what it does.\n\n</details>\n\n<details>\n<summary><strong>How do I find who unfollowed me on Twitter?</strong></summary>\n\nUse `src/detectUnfollowers.js` - it saves a snapshot of your followers and compares on next run.\n</details>\n\n<details>\n<summary><strong>How do I download Twitter/X videos?</strong></summary>\n\nUse `src/scrapers/videoDownloader.js` - extracts MP4 URLs from any tweet.\n</details>\n\n<details>\n<summary><strong>Twitter API alternative that's free?</strong></summary>\n\nXActions uses browser automation instead of the API. No API keys needed, no rate limits, no $100/mo fee.\n</details>\n\n<details>\n<summary><strong>Hypefury / Tweethunter alternative?</strong></summary>\n\nXActions is open-source and completely free for humans. AI agents pay micropayments per request.\n</details>\n\n---\n\n## ⚠️ Disclaimer\n\n> [!WARNING]\n> **Educational Material Only**\n>\n> This project is provided for **educational and research purposes only**. The scripts and tools have not been extensively tested on personal accounts. \n>\n> - Use at your own risk\n> - We are not responsible for any account restrictions or bans\n> - Always comply with X/Twitter's Terms of Service\n> - Start with small batches and test carefully\n>\n> **For X/Twitter:** If you have concerns about this project or would like us to modify or remove any functionality, please contact [@nichxbt](https://x.com/nichxbt) directly. We're happy to work with you.\n>\n> **Acknowledgment:** This project was inspired by the innovation happening at X and xAI. We admire Elon Musk's vision for making X the everything app and Grok's approach to AI. XActions aims to help developers and researchers explore the platform's capabilities while respecting its ecosystem.\n\n---\n\n## 🚀 Quick Start Examples\n\n### Sixty seconds, no account\n\nMost reads work the moment you install. You do not need an X account, an API key, or a browser.\n\n```bash\nnpm install -g xactions\n\nxactions doctor                      # what works right now, and why\nxactions profile NASA                # any public account\nxactions analyze NASA                # engagement rate, cadence, content mix, best hour\nxactions tweets NASA --limit 50 --json | jq -r '.[].text'\n```\n\nThen log in once, in a real browser, to unlock search, followers, following, likes, bookmarks, and DMs:\n\n```bash\nxactions connect\nxactions search \"your topic\" --limit 50\n```\n\nRunning `xactions` with no arguments prints all 56 commands grouped by task. `xactions completion bash` (or `zsh`, `fish`) turns on tab completion.\n\n### Example 1: Unfollow Non-Followers (30 seconds)\n\n**Browser Console**: *No install required!*\n```javascript\n// Go to: x.com/YOUR_USERNAME/following\n// Press F12 → Console → Paste this:\n\n(() => {\n  const sleep = (s) => new Promise(r => setTimeout(r, s * 1000));\n  const run = async () => {\n    const buttons = [...document.querySelectorAll('[data-testid$=\"-unfollow\"]')]\n      .filter(b => !b.closest('[data-testid=\"UserCell\"]')\n        ?.querySelector('[data-testid=\"userFollowIndicator\"]'));\n    \n    for (const btn of buttons) {\n      btn.click();\n      await sleep(1);\n      document.querySelector('[data-testid=\"confirmationSheetConfirm\"]')?.click();\n      await sleep(2);\n    }\n    window.scrollTo(0, document.body.scrollHeight);\n    await sleep(2);\n    if (document.querySelectorAll('[data-testid$=\"-unfollow\"]').length) run();\n    else console.log('✅ Done! Reload page to continue.');\n  };\n  run();\n})();\n```\n\n**CLI:**\n```bash\nxactions login\nxactions non-followers YOUR_USERNAME --output non-followers.json\n```\n\n**Node.js:**\n```javascript\nimport { createBrowser, createPage, scrapeFollowing } from 'xactions';\n\nconst browser = await createBrowser();\nconst page = await createPage(browser);\nconst following = await scrapeFollowing(page, 'your_username', { limit: 500 });\nconst nonFollowers = following.filter(u => !u.followsBack);\nconsole.log(`Found ${nonFollowers.length} non-followers`);\nawait browser.close();\n```\n\n> 💡 **Don't want to code?** Use [xactions.app](https://xactions.app): just login and click!\n\n---\n\n### Example 2: Scrape Any Profile\n\n**Browser Console:**\n```javascript\n// Go to any profile on x.com, then run:\n\n(() => {\n  const profile = {\n    name: document.querySelector('[data-testid=\"UserName\"]')?.textContent?.split('@')[0]?.trim(),\n    username: location.pathname.slice(1),\n    bio: document.querySelector('[data-testid=\"UserDescription\"]')?.textContent,\n    followers: document.querySelector('a[href$=\"/followers\"] span')?.textContent,\n    following: document.querySelector('a[href$=\"/following\"] span')?.textContent,\n  };\n  console.log(profile);\n  copy(JSON.stringify(profile, null, 2)); // Copies to clipboard!\n})();\n```\n\n**CLI:**\n```bash\nxactions profile elonmusk --json\n```\n\n**Node.js:**\n```javascript\nimport { createBrowser, createPage, scrapeProfile } from 'xactions';\n\nconst browser = await createBrowser();\nconst page = await createPage(browser);\nconst profile = await scrapeProfile(page, 'elonmusk');\nconsole.log(profile);\n// { name: 'Elon Musk', followers: '200M', bio: '...', ... }\nawait browser.close();\n```\n\n---\n\n### Example 3: Search & Scrape Tweets\n\n**Browser Console:**\n```javascript\n// Go to: x.com/search?q=YOUR_KEYWORD&f=live\n\n(() => {\n  const tweets = [...document.querySelectorAll('article[data-testid=\"tweet\"]')]\n    .map(article => ({\n      text: article.querySelector('[data-testid=\"tweetText\"]')?.textContent,\n      author: article.querySelector('[data-testid=\"User-Name\"] a')?.href?.split('/')[3],\n      time: article.querySelector('time')?.getAttribute('datetime'),\n    }));\n  console.table(tweets);\n  copy(JSON.stringify(tweets, null, 2));\n})();\n```\n\n**CLI:**\n```bash\nxactions search \"AI startup\" --limit 100 --output ai-tweets.json\n```\n\n**Node.js:**\n```javascript\nimport { createBrowser, createPage, searchTweets } from 'xactions';\n\nconst browser = await createBrowser();\nconst page = await createPage(browser);\nconst tweets = await searchTweets(page, 'AI startup', { limit: 100 });\nconsole.log(`Found ${tweets.length} tweets`);\nawait browser.close();\n```\n\n---\n\n### Example 4: Detect Who Unfollowed You\n\n**Browser Console:**\n```javascript\n// Go to: x.com/YOUR_USERNAME/followers\n\n(() => {\n  const KEY = 'xactions_followers';\n  const sleep = (ms) => new Promise(r => setTimeout(r, ms));\n  \n  const scrape = async () => {\n    const users = new Set();\n    let retries = 0;\n    while (retries < 5) {\n      document.querySelectorAll('[data-testid=\"UserCell\"] a')\n        .forEach(a => users.add(a.href.split('/')[3]?.toLowerCase()));\n      window.scrollTo(0, document.body.scrollHeight);\n      await sleep(1500);\n      retries++;\n    }\n    return [...users].filter(Boolean);\n  };\n\n  scrape().then(current => {\n    const saved = localStorage.getItem(KEY);\n    if (saved) {\n      const old = JSON.parse(saved);\n      const gone = old.filter(u => !current.includes(u));\n      console.log('🚨 Unfollowed you:', gone);\n    }\n    localStorage.setItem(KEY, JSON.stringify(current));\n    console.log(`💾 Saved ${current.length} followers`);\n  });\n})();\n```\n\n**CLI:**\n```bash\n# First run saves snapshot\nxactions followers YOUR_USERNAME --output snapshot1.json\n\n# Later, compare\nxactions followers YOUR_USERNAME --output snapshot2.json\n# Use diff tools to compare\n```\n\n---\n\n### Example 5: Auto-Like Posts by Keyword\n\n**Browser Console:**\n```javascript\n// Go to: x.com/search?q=YOUR_KEYWORD&f=live\n\n(async () => {\n  const sleep = (s) => new Promise(r => setTimeout(r, s * 1000));\n  const liked = new Set();\n  \n  while (liked.size < 20) { // Like 20 posts\n    const buttons = [...document.querySelectorAll('[data-testid=\"like\"]')]\n      .filter(b => !liked.has(b));\n    \n    for (const btn of buttons.slice(0, 3)) {\n      btn.click();\n      liked.add(btn);\n      console.log(`❤️ Liked ${liked.size} posts`);\n      await sleep(3 + Math.random() * 2); // Random delay\n    }\n    window.scrollTo(0, document.body.scrollHeight);\n    await sleep(2);\n  }\n  console.log('✅ Done!');\n})();\n```\n\n> ⚠️ **Go slow!** Twitter may rate-limit you. The website version handles this automatically.\n\n---\n\n### Example 6: Leave All Communities\n\n**Browser Console:**\n```javascript\n// Go to: x.com/YOUR_USERNAME/communities\n\n(() => {\n  const $communityLinks = 'a[href^=\"/i/communities/\"]';\n  const $joinedButton = 'button[aria-label^=\"Joined\"]';\n  const $confirmButton = '[data-testid=\"confirmationSheetConfirm\"]';\n  const $communitiesNav = 'a[aria-label=\"Communities\"]';\n\n  const getLeftCommunities = () => {\n    try { return JSON.parse(sessionStorage.getItem('xactions_left_ids') || '[]'); }\n    catch { return []; }\n  };\n  const markAsLeft = (id) => {\n    const left = getLeftCommunities();\n    if (!left.includes(id)) {\n      left.push(id);\n      sessionStorage.setItem('xactions_left_ids', JSON.stringify(left));\n    }\n  };\n\n  const sleep = (ms) => new Promise(r => setTimeout(r, ms));\n  const getCommunityId = () => {\n    const leftAlready = getLeftCommunities();\n    for (const link of document.querySelectorAll($communityLinks)) {\n      const match = link.href.match(/\\/i\\/communities\\/(\\d+)/);\n      if (match && !leftAlready.includes(match[1])) return { id: match[1], element: link };\n    }\n    return null;\n  };\n\n  const run = async () => {\n    console.log(`🚀 Left so far: ${getLeftCommunities().length}`);\n    await sleep(1500);\n    const joinedBtn = document.querySelector($joinedButton);\n    if (joinedBtn) {\n      const urlMatch = window.location.href.match(/\\/i\\/communities\\/(\\d+)/);\n      const currentId = urlMatch ? urlMatch[1] : null;\n      joinedBtn.click();\n      await sleep(1000);\n      const confirmBtn = document.querySelector($confirmButton);\n      if (confirmBtn) { confirmBtn.click(); if (currentId) markAsLeft(currentId); await sleep(1500); }\n      const communitiesLink = document.querySelector($communitiesNav);\n      if (communitiesLink) { communitiesLink.click(); await sleep(2500); return run(); }\n    }\n    const community = getCommunityId();\n    if (community) { community.element.click(); await sleep(2500); return run(); }\n    else { console.log(`🎉 DONE! Left ${getLeftCommunities().length} communities`); sessionStorage.removeItem('xactions_left_ids'); }\n  };\n  run();\n})();\n```\n\n> 📖 Full documentation: [docs/examples/leave-all-communities.md](docs/examples/leave-all-communities.md)\n\n---\n\n## 📋 Complete Feature List\n\n### Feature Availability Matrix\n\n| Feature | Console Script | CLI | Node.js | Website |\n|---------|:-------------:|:---:|:-------:|:-------:|\n| **SCRAPING** |\n| Scrape Profile | ✅ | ✅ | ✅ | ✅ |\n| Scrape Followers | ✅ | ✅ | ✅ | ✅ |\n| Scrape Following | ✅ | ✅ | ✅ | ✅ |\n| Scrape Tweets | ✅ | ✅ | ✅ | ✅ |\n| Search Tweets | ✅ | ✅ | ✅ | ✅ |\n| Scrape Thread | ✅ | ✅ | ✅ | ✅ |\n| Scrape Hashtag | ✅ | ✅ | ✅ | ✅ |\n| Scrape Media | ✅ | ✅ | ✅ | ✅ |\n| Scrape List Members | ✅ | ✅ | ✅ | ✅ |\n| Scrape Likes | ✅ | ✅ | ✅ | ✅ |\n| **UNFOLLOW** |\n| Unfollow Non-Followers | ✅ | ✅ | ✅ | ✅ |\n| Unfollow Everyone | ✅ | ✅ | ✅ | ✅ |\n| Smart Unfollow (after X days) | ⚠️ | ✅ | ✅ | ✅ |\n| Unfollow with Logging | ✅ | ✅ | ✅ | ✅ |\n| **FOLLOW** |\n| Follow User | ✅ | ✅ | ✅ | ✅ |\n| Keyword Follow | ⚠️ | ✅ | ✅ | ✅ |\n| Follow Engagers | ⚠️ | ✅ | ✅ | ✅ |\n| Follow Target's Followers | ⚠️ | ✅ | ✅ | ✅ |\n| **ENGAGEMENT** |\n| Like Tweet | ✅ | ✅ | ✅ | ✅ |\n| Retweet | ✅ | ✅ | ✅ | ✅ |\n| Auto-Liker | ⚠️ | ✅ | ✅ | ✅ |\n| Auto-Commenter | ⚠️ | ✅ | ✅ | ✅ |\n| Post Tweet | ✅ | ✅ | ✅ | ✅ |\n| **MONITORING** |\n| Detect Unfollowers | ✅ | ✅ | ✅ | ✅ |\n| New Follower Alerts | ✅ | ✅ | ✅ | ✅ |\n| Monitor Any Account | ✅ | ✅ | ✅ | ✅ |\n| Continuous Monitoring | ⚠️ | ✅ | ✅ | ✅ |\n| **COMMUNITIES** |\n| Leave All Communities | ✅ | ⚠️ | ⚠️ | ⚠️ |\n| **SPACES** |\n| Discover Live Spaces | ✅ | ✅ | ✅ | ✅ |\n| Scrape Space Metadata | ✅ | ✅ | ✅ | ✅ |\n| AI Agent Joins Space | ❌ | ✅ | ✅ | ❌ |\n| Agent Listens & Speaks | ❌ | ✅ | ✅ | ❌ |\n| **ADVANCED** |\n| Multi-Account | ❌ | ✅ | ✅ | ✅ Pro |\n| Link Scraper | ✅ | ✅ | ✅ | ✅ |\n| Growth Suite | ❌ | ✅ | ✅ | ✅ Pro |\n| Customer Service Bot | ❌ | ✅ | ✅ | ✅ Pro |\n| MCP Server (AI Agents) | ❌ | ✅ | ✅ | ❌ |\n| Export to CSV/JSON | ✅ | ✅ | ✅ | ✅ |\n\n**Legend:** ✅ Full Support | ⚠️ Basic/Manual | ❌ Not Available\n\n---\n\n## 🤖 MCP Server (AI Agents)\n\nXActions includes the most comprehensive free MCP server for X/Twitter. Works with **Claude, Cursor, Windsurf, VS Code**, and any MCP client.\n\n### Quick Setup (30 seconds)\n\nAdd to your Claude Desktop config (`claude_desktop_config.json`):\n```json\n{\n  \"mcpServers\": {\n    \"xactions\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"xactions-mcp\"],\n      \"env\": {\n        \"XACTIONS_SESSION_COOKIE\": \"your_auth_token_here\"\n      }\n    }\n  }\n}\n```\n\n> **Get your auth_token**: x.com → DevTools (F12) → Application → Cookies → copy `auth_token` value\n\nOr auto-generate the config:\n```bash\nnpx xactions mcp-config --client claude\nnpx xactions mcp-config --client cursor\nnpx xactions mcp-config --client windsurf\n```\n\n### Available MCP Tools (152)\n\n| Category | Tools |\n|----------|-------|\n| **Scraping** | `x_get_profile`, `x_get_followers`, `x_get_following`, `x_get_tweets`, `x_search_tweets`, `x_get_thread`, `x_download_video`, `x_get_replies`, `x_get_hashtag`, `x_get_likers`, `x_get_retweeters`, `x_get_media`, `x_get_mentions`, `x_get_quote_tweets`, `x_get_likes`, `x_get_recommendations` |\n| **Analysis** | `x_detect_unfollowers`, `x_analyze_sentiment`, `x_best_time_to_post`, `x_competitor_analysis`, `x_brand_monitor`, `x_audience_insights`, `x_engagement_report`, `x_crypto_analyze` |\n| **Actions** | `x_follow`, `x_unfollow`, `x_like`, `x_post_tweet`, `x_post_thread`, `x_reply`, `x_retweet`, `x_quote_tweet`, `x_bookmark`, `x_send_dm`, `x_create_poll`, `x_delete_tweet` |\n| **Automation** | `x_auto_follow`, `x_follow_engagers`, `x_unfollow_all`, `x_smart_unfollow`, `x_auto_comment`, `x_auto_retweet`, `x_auto_like`, `x_engage`, `x_unfollow_non_followers` |\n| **AI** | `x_analyze_voice`, `x_generate_tweet`, `x_summarize_thread`, `x_rewrite_tweet`, `x_detect_bots`, `x_find_influencers`, `x_smart_target`, `x_grok_analyze_image` |\n| **Monitoring** | `x_monitor_account`, `x_monitor_keyword`, `x_follower_alerts`, `x_track_engagement`, `x_monitor_reputation`, `x_stream_start` |\n| **Workflows** | `x_workflow_create`, `x_workflow_run`, `x_workflow_list`, `x_workflow_actions` |\n| **Persona** | `x_persona_create`, `x_persona_run`, `x_persona_edit`, `x_persona_list`, `x_persona_presets` |\n| **Portability** | `x_export_account`, `x_migrate_account`, `x_diff_exports`, `x_import_data`, `x_convert_format` |\n| **Spaces** | `x_get_spaces`, `x_scrape_space`, `x_space_join`, `x_space_leave`, `x_space_status`, `x_space_transcript` |\n| **Graph** | `x_graph_build`, `x_graph_analyze`, `x_graph_recommendations`, `x_graph_list` |\n| **Drafts** | `x_list_drafts`, `x_approve_draft`, `x_discard_draft`, `x_draft_status` |\n\nEvery tool belongs to exactly one group, and the list is filterable, so a client\nloads only what the session needs:\n\n```bash\nnpx xactions-mcp --tools read,analytics     # advertise these groups only\nnpx xactions-mcp --exclude write,dm         # or subtract from the full list\nXACTIONS_MCP_TOOLS=read npx xactions-mcp    # same thing through the environment\n```\n\nA filtered tool is neither advertised nor callable. Groups, largest first:\n`read`, `analytics`, `write`, `monitoring`, `data`, `workflows`, `automation`,\n`ai`, `persona`, `spaces`, `graph`, `drafts`, `dm`, `grok`, `lists`, `auth`,\nplus `x402` when the server runs in remote mode.\n\n### Hold every write for a human\n\n```bash\nXACTIONS_MCP_REQUIRE_APPROVAL=1 npx xactions-mcp\n```\n\nEvery tool that posts, deletes, follows, mutes or sends is then saved as a\ndraft instead of running. Release or bin them with `x_list_drafts`,\n`x_approve_draft` and `x_discard_draft`, or from the shell with\n`xactions drafts list`, `xactions drafts approve <id>` and\n`xactions drafts discard <id>`.\n\nIndependently of that gate, every write is charged against a rolling 24 hour\nper-account cap held in a file under `~/.xactions`, so it survives a restart\nand a call that would exceed it never reaches X.\n\n### Run the server over HTTP\n\n```bash\nnpx xactions-mcp --http --port 3000    # Streamable HTTP on /mcp\n```\n\nstdio is the default and is what a local client wants. `--http` (or\n`MCP_TRANSPORT=http`) is for remote and hosted clients; set\n`XACTIONS_MCP_TOKEN` to require `Authorization: Bearer <token>` on it.\n\n### Install into Claude Desktop with no config file\n\nThe `.mcpb` bundle carries the server and its dependencies and prompts for the\nsession cookie and the tool groups at install time. Download it from the\n[latest release](https://github.com/nirholas/xactions/releases) and drag it\nonto Claude Desktop > Settings > Extensions.\n\n### Example Prompts\n\n> **\"Analyze @paulg's writing style and generate 3 tweet ideas about startups in his voice\"**\n> → Scrapes tweets → analyzes voice → generates content with AI\n\n> **\"Find everyone I follow who doesn't follow me back, sorted by follower count\"**\n> → Uses x_get_following + x_get_followers → computes diff → formats results\n\n> **\"Compare the engagement metrics of @openai, @anthropic, and @google\"**\n> → Scrapes profiles + recent tweets → computes avg engagement → presents comparison\n\n📖 **Full setup guide**: [docs/mcp-setup.md](docs/mcp-setup.md)\n\n---\n\n## 🎙️ Autonomous Space Agent\n\nAI agents can **join live X Spaces**, listen to conversations, and speak autonomously using voice AI. Powered by the [`xspace-agent`](https://github.com/nirholas/xspace-agent) SDK.\n\n### What It Does\n\n1. Launches a headless browser and joins an X Space\n2. Transcribes other speakers in real time (Whisper STT)\n3. Generates intelligent responses with your chosen LLM (OpenAI, Claude, or Groq)\n4. Speaks responses back into the Space via text-to-speech (ElevenLabs, OpenAI, or browser)\n5. Handles turn-taking, context tracking, and graceful shutdown\n\n### Setup\n\n```bash\nnpm install xactions xspace-agent\n```\n\nSet your credentials:\n```bash\nexport X_AUTH_TOKEN=\"your_auth_token\"     # From x.com cookies\nexport X_CT0=\"your_ct0_token\"            # From x.com cookies\nexport OPENAI_API_KEY=\"sk-...\"           # Or ANTHROPIC_API_KEY / GROQ_API_KEY\n```\n\n### Usage\n\n**MCP (Claude Desktop / Cursor):**\n> *\"Join this Space as an AI agent: https://x.com/i/spaces/1abc123\"*\n\nClaude calls `x_space_join` and your agent enters the Space.\n\n**Node.js:**\n```javascript\nimport { joinSpace, leaveSpace } from 'xactions/spaces/agent';\n\nawait joinSpace({\n  url: 'https://x.com/i/spaces/1abc123',\n  provider: 'openai',\n  systemPrompt: 'You are a helpful AI participant. Keep responses concise.',\n});\n\n// Later...\nconst summary = await leaveSpace();\n// { duration: '300s', transcriptions: 42, responses: 8 }\n```\n\n**MCP Tools:**\n\n| Tool | Description |\n|------|-------------|\n| `x_space_join` | Join a Space with an autonomous AI voice agent |\n| `x_space_leave` | Leave the active Space and get session summary |\n| `x_space_status` | Get agent status (duration, transcription/response counts) |\n| `x_space_transcript` | Get recent transcriptions from the active Space |\n\n📖 **Full guide**: [docs/spaces-agent.md](docs/spaces-agent.md): configuration, environment variables, events, multi-agent setup, and examples.\n\n---\n\n## 💻 CLI Reference\n\n56 commands, grouped by task, with 85 subcommands under them. Run `xactions`\nwith no arguments for the grouped screen, `xactions help <command>` for one\ncommand, and `xactions completion bash|zsh|fish` for tab completion generated\nfrom the live command tree.\n\n**Start here** `quickstart` `doctor` `connect` `login` `logout` `mcp-config` `skills` `drafts` `info`\n\n```bash\nxactions quickstart         # guided first run, adapts to what you already have\nxactions doctor             # what works right now, and what each failure needs\nxactions connect            # log in through a real browser, no DevTools\nxactions login --from-browser chrome    # or read cookies from an installed browser\nxactions login --cookies-file cookies.txt   # or import a cookie export\nxactions skills install --all           # 50 agent skills into Claude Code, Cursor, Codex, Windsurf\nxactions drafts list                    # MCP writes waiting for your approval\n```\n\n**Read an account** (no login needed) `profile` `tweets` `thread` `media` `analyze` `report` `history` `snapshot`\n\n```bash\nxactions profile NASA\nxactions tweets NASA --limit 50 --output nasa.csv\nxactions thread https://x.com/NASA/status/1234567890\nxactions media NASA --limit 30\nxactions analyze NASA SpaceX          # engagement rate, cadence, content mix, best hour\n```\n\n**Followers and audience** `followers` `following` `non-followers` `audience` `crm` `graph`\n\n```bash\nxactions followers YOUR_USERNAME --limit 1000 --output followers.json\nxactions non-followers YOUR_USERNAME  # who does not follow back\nxactions audience nasa spacex         # follower overlap between two accounts\nxactions graph build nasa             # build and analyse a social graph\n```\n\n**Search and monitor** `search` `hashtag` `scrape` `platforms` `monitor` `sentiment` `rss` `stream`\n\n```bash\nxactions search \"your brand\" --filter latest --limit 50\nxactions hashtag ai --limit 50\nxactions monitor yourbrand            # sentiment over time\nxactions stream start tweet nasa      # tweet, follower or mention streams\n```\n\n**Write and grow** `engage` `ai` `optimize` `hashtags` `predict` `variations` `evergreen` `persona` `schedule` `bulk`\n\n```bash\nxactions engage USERNAME --like --repost --comment --prompt \"supportive, one honest question\"\nxactions ai generate \"shipping fast\" --voice nichxbt\nxactions evergreen YOUR_USERNAME      # find and recycle top performers\nxactions persona run my-persona\n```\n\n**Automate** `workflow` `agent` `notify` `plugin` `team` `dataset`\n\n```bash\nxactions workflow run daily-digest\nxactions notify test slack\n```\n\n**Move data** `export` `export-data` `archive` `import` `convert` `migrate` `diff`\n\n```bash\nxactions export YOUR_USERNAME             # profile, tweets, followers, following, bookmarks\nxactions archive summary ~/Downloads/twitter-archive.zip\nxactions archive migrate ~/Downloads/twitter-archive.zip --to bluesky --execute\nxactions diff exports/january exports/february\n```\n\n**Low level** `client`\n\n```bash\nxactions client profile nasa          # the raw HTTP client, no browser at all\n```\n\n### Output flags for agents and pipes\n\nGlobal on every read command:\n\n```bash\nxactions profile NASA --compact                              # one record per line, key=value\nxactions tweets NASA --limit 200 --fields id,likes,text --compact\nxactions tweets NASA --limit 200 --json | jq 'sort_by(-.likes) | .[:5]'\n```\n\n`--compact` prints tab-separated `key=value` pairs with no colours or spinners.\n`--fields` narrows that to the columns you name, in the order you name them.\n`--json` prints the full structured object and outranks `--output`, so a pipe is\nnever silently turned into a file write. If both `--compact` and `--json` are\npassed, `--compact` wins.\n\nPublic reads work with no account: `profile`, `tweets`, `thread`, `media`,\n`analyze`, `hashtag`. Search, `followers`, `following`, `non-followers`, likes,\nbookmarks and DMs need a session. Full reference:\n[docs/cli-reference.md](docs/cli-reference.md).\n\n---\n\n## 📚 Node.js API\n\n### Quick Start\n```javascript\nimport { \n  createBrowser, \n  createPage, \n  loginWithCookie,\n  scrapeProfile,\n  scrapeFollowers,\n  scrapeFollowing,\n  scrapeTweets,\n  searchTweets,\n  exportToJSON,\n  exportToCSV \n} from 'xactions';\n\n// Initialize\nconst browser = await createBrowser({ headless: true });\nconst page = await createPage(browser);\n\n// Optional: Login for private data\nawait loginWithCookie(page, 'your_auth_token_cookie');\n\n// Scrape profile\nconst profile = await scrapeProfile(page, 'elonmusk');\n\n// Scrape followers with progress\nconst followers = await scrapeFollowers(page, 'elonmusk', {\n  limit: 1000,\n  onProgress: ({ scraped, limit }) => console.log(`${scraped}/${limit}`)\n});\n\n// Export data\nawait exportToJSON(followers, 'followers.json');\nawait exportToCSV(followers, 'followers.csv');\n\nawait browser.close();\n```\n\n### All Scraper Functions\n\n```javascript\n// Profile\nscrapeProfile(page, username)\n\n// Followers & Following\nscrapeFollowers(page, username, { limit, onProgress })\nscrapeFollowing(page, username, { limit, onProgress })\n\n// Tweets\nscrapeTweets(page, username, { limit, includeReplies, onProgress })\nsearchTweets(page, query, { limit, filter: 'latest'|'top' })\nscrapeThread(page, tweetUrl)\nscrapeHashtag(page, hashtag, { limit, filter })\n\n// Media\nscrapeMedia(page, username, { limit })\nscrapeLikes(page, tweetUrl, { limit })\n\n// Lists\nscrapeListMembers(page, listUrl, { limit })\n\n// Export\nexportToJSON(data, filename)\nexportToCSV(data, filename)\n```\n\n---\n\n## 🌐 Don't Want to Code?\n\n<div align=\"center\">\n\n**Visit [xactions.app](https://xactions.app) for a no-code solution**\n\nUse browser scripts &nbsp;·&nbsp; Copy-paste console scripts &nbsp;·&nbsp; View tutorials\n\n**100% Free.** No API keys, no payments, no limits.\n\n</div>\n\n---\n\n## 🔒 Safety & Best Practices\n\n<table>\n<tr>\n<td>\n\n**Rate Limiting**: Built-in 1-3s delays, human-like scrolling, auto-pause on rate limits\n\n</td>\n</tr>\n<tr>\n<td>\n\n**Auth Token**: `x.com` → DevTools (F12) → Application → Cookies → copy `auth_token`\n\n</td>\n</tr>\n</table>\n\n> [!CAUTION]\n> **Do:** Use 2–5s delays · Mix automated with manual activity · Test with small batches\n> \n> **Don't:** Mass-follow thousands/day · Run 24/7 · Spam comments\n\n---\n\n## 🛠️ Built With\n\n<p>\n  <img src=\"https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=node.js&logoColor=white\" alt=\"Node.js\">\n  <img src=\"https://img.shields.io/badge/Puppeteer-40B5A4?style=for-the-badge&logo=puppeteer&logoColor=white\" alt=\"Puppeteer\">\n  <img src=\"https://img.shields.io/badge/Express-000000?style=for-the-badge&logo=express&logoColor=white\" alt=\"Express\">\n  <img src=\"https://img.shields.io/badge/Prisma-2D3748?style=for-the-badge&logo=prisma&logoColor=white\" alt=\"Prisma\">\n  <img src=\"https://img.shields.io/badge/Socket.IO-010101?style=for-the-badge&logo=socket.io&logoColor=white\" alt=\"Socket.IO\">\n  <img src=\"https://img.shields.io/badge/Redis-DC382D?style=for-the-badge&logo=redis&logoColor=white\" alt=\"Redis\">\n  <img src=\"https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white\" alt=\"Docker\">\n  <img src=\"https://img.shields.io/badge/MCP_SDK-8B5CF6?style=for-the-badge\" alt=\"MCP SDK\">\n</p>\n\n---\n\n## 📁 Project Structure\n\nEvery top-level directory, so nothing here is a surprise.\n\n```\nsrc/            The library. cli/ mcp/ scrapers/ client/ automation/ agents/\n                analytics/ streaming/ workflows/ plugins/ portability/ graph/\n                a2a/ spaces/ ai/ auth/ scheduler/ notifications/, plus the\n                browser console scripts that sit at the top level\napi/            Express REST API: routes/ services/ middleware/ realtime/\nbin/            Legacy command name (unfollowx), forwards to the CLI\npackages/       xactions-mcp, the thin MCP wrapper published to npm\nskills/         50 Agent Skills, one directory each\nextension/      Chrome and Edge extension (Manifest V3)\nintegrations/   Third-party glue (n8n and friends)\nworker/         Cloudflare Worker entry point\nfunctions/      Cloudflare Pages Functions for the /api/* edge surface\n\nsite/           The marketing landing page served at /\ndashboard/      The signed-in app shell at /dashboard, plus the generated\n                docs, guides, skills and script pages the site serves\npublic/         Static assets: OG images, robots.txt, sitemap\nplayground/     Standalone in-browser playground\n\ndocs/           Documentation source (Markdown)\ntutorials/      Guided walkthroughs\nexamples/       Runnable programs, from a profile lookup to the MCP draft gate\nprompts/        Prompt library for coding agents\n\ntests/          Vitest suite\nscripts/        The 95 browser console scripts, plus build, docs and\n                maintenance tooling. twitter/ holds standalone console variants\nconfig/         Agent, niche and persona configuration\nprisma/         Database schema and migrations\ndeploy/         Cloudflare and GCP deployment assets\ntypes/          TypeScript declarations\ndata/           Runtime output (gitignored, keeps a .gitkeep)\narchive/        Retired code, kept for reference. Do not modify\n\npython/         xeepy, the Python twin of the library\nxspace-agents/  The Spaces agent monorepo\n```\n\nBoth `python/` and `xspace-agents/` are self-contained projects that live in this\nrepository but build on their own. Start from their READMEs, not this one.\n\n---\n\n## 🤝 Contributing\n\nContributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md), and\n[AGENTS.md](AGENTS.md) for the repository map and the three runtime contexts.\n\n```bash\ngit clone https://github.com/nirholas/xactions.git\ncd xactions && npm install\nnpm run cli -- profile elonmusk   # run the CLI from the source tree\nnpm run mcp                       # run the MCP server\n```\n\nNode.js 20 or newer is required (`engines.node` is `>=20`); CI runs the suite on\n20, 22 and 24. Three commands before you open a PR, all of which run in CI:\n\n```bash\nnpm test              # the whole suite, offline, under a minute\nnpm run lint          # ESLint over the repo\nnpm run docs:check    # dead links, stale counts, invented CLI commands\n```\n\n---\n\n## ⭐ Star History\n\nIf XActions saved you from paying $100/mo for Twitter's API, **star the repo**: it's how open source grows.\n\n<a href=\"https://star-history.com/#nirholas/xactions&Date\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=nirholas/xactions&type=Date&theme=dark\">\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=nirholas/xactions&type=Date\">\n    <img alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=nirholas/xactions&type=Date\" width=\"600\">\n  </picture>\n</a>\n\n---\n\n## 📚 Full Tutorial Library\n\n**XActions is 100% free and open source.** Visit [xactions.app](https://xactions.app) for interactive tutorials.\n\n### 🚀 One-Click Script Runner\n\n**NEW!** Run scripts without any coding knowledge:\n\n1. Visit [xactions.app/run.html](https://xactions.app/run.html)\n2. Drag any blue button to your bookmarks bar\n3. Go to x.com and click the bookmarklet\n\nNo console, no code, no setup!\n\n### Quick Links by Category\n\n| Category | Scripts | Tutorial |\n|----------|---------|----------|\n| **Unfollow** | Unfollow Everyone, Non-Followers, Smart Unfollow | [Tutorial](https://xactions.app/tutorials/unfollow) |\n| **Automation** | Auto-Liker, Auto-Commenter, Follow Engagers | [Tutorial](https://xactions.app/tutorials/automation) |\n| **Scraping** | Video Download, Followers, Tweets, Hashtags | [Tutorial](https://xactions.app/tutorials/scrapers) |\n| **Monitoring** | Detect Unfollowers, Track Accounts, Alerts | [Tutorial](https://xactions.app/tutorials/monitoring) |\n| **Communities** | Leave All Communities | [Tutorial](https://xactions.app/tutorials/communities) |\n| **AI/MCP** | Claude Desktop, GPT Integration | [Tutorial](https://xactions.app/tutorials/mcp) |\n\n### All Documentation\n\n- [Getting Started](docs/getting-started.md)\n- [CLI Reference](docs/cli-reference.md)\n- [Automation Guide](docs/automation.md)\n- [Monitoring Guide](docs/monitoring.md)\n\n### Example Docs (Full Code)\n\n| Feature | Documentation |\n|---------|---------------|\n| Unfollow Everyone | [unfollow-everyone.md](docs/examples/unfollow-everyone.md) |\n| Unfollow Non-Followers | [unfollow-non-followers.md](docs/examples/unfollow-non-followers.md) |\n| Detect Unfollowers | [detect-unfollowers.md](docs/examples/detect-unfollowers.md) |\n| Auto-Liker | [auto-liker.md](docs/examples/auto-liker.md) |\n| Auto-Commenter | [auto-commenter.md](docs/examples/auto-commenter.md) |\n| Follow Engagers | [follow-engagers.md](docs/examples/follow-engagers.md) |\n| Video Downloader | [video-downloader.md](docs/examples/video-downloader.md) |\n| Followers Scraping | [followers-scraping.md](docs/examples/followers-scraping.md) |\n| Tweet Scraping | [tweet-scraping.md](docs/examples/tweet-scraping.md) |\n| Leave Communities | [leave-all-communities.md](docs/examples/leave-all-communities.md) |\n| MCP Server | [mcp-server.md](docs/examples/mcp-server.md) |\n| Monitor Account | [monitor-account.md](docs/examples/monitor-account.md) |\n| New Follower Alerts | [new-follower-alerts.md](docs/examples/new-follower-alerts.md) |\n\n---\n\n<p align=\"center\">\n  <b>⚡ XActions</b>, the complete X/Twitter automation toolkit<br>\n  <b>100% Free & Open Source</b> · Apache 2.0 License<br><br>\n  <a href=\"https://xactions.app\">xactions.app</a> · \n  <a href=\"https://github.com/nirholas/xactions\">GitHub</a> · \n  <a href=\"https://x.com/nichxbt\">@nichxbt</a><br><br>\n  <a href=\"https://github.com/nirholas/xactions\"><img src=\"https://img.shields.io/badge/⭐_Star_this_repo-f5c542?style=for-the-badge\" alt=\"Star this repo\"></a>&nbsp;\n  <a href=\"https://github.com/nirholas/xactions/issues\"><img src=\"https://img.shields.io/badge/🐛_Report_Bug-ef4444?style=for-the-badge\" alt=\"Report Bug\"></a>&nbsp;\n  <a href=\"https://github.com/nirholas/xactions/issues\"><img src=\"https://img.shields.io/badge/💡_Request_Fea",
  "bytes": 60000,
  "sha": "fc325030101af4cdb793fa0d6fabf1aaa130be41229f5a1dc564ca38cda717f9",
  "repo_slug": "nirholas/xactions",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_nirholas_xactions_0e4ee1f0/readme"
}