{"id":47145490,"url":"https://github.com/benoitpetit/xsh","last_synced_at":"2026-04-06T00:11:28.282Z","repository":{"id":344057706,"uuid":"1179987823","full_name":"benoitpetit/xsh","owner":"benoitpetit","description":"Twitter/X CLI without API keys. xsh is a command-line interface for Twitter/X that works with cookie-based authentication. No developer account, no API keys, no rate limit headaches. Just log in with your browser and go.","archived":false,"fork":false,"pushed_at":"2026-03-27T10:29:52.000Z","size":6031,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-27T10:41:56.062Z","etag":null,"topics":["cli","command-line-tool","free","noapikey","twitter-x","x-twitter"],"latest_commit_sha":null,"homepage":"https://x.com/devbyben","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benoitpetit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"liberapay":"devbyben/donate"}},"created_at":"2026-03-12T15:29:24.000Z","updated_at":"2026-03-27T10:29:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/benoitpetit/xsh","commit_stats":null,"previous_names":["benoitpetit/xsh"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/benoitpetit/xsh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fxsh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fxsh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fxsh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fxsh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benoitpetit","download_url":"https://codeload.github.com/benoitpetit/xsh/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fxsh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31454237,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"ssl_error","status_checked_at":"2026-04-05T21:22:51.943Z","response_time":75,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-line-tool","free","noapikey","twitter-x","x-twitter"],"created_at":"2026-03-13T00:04:46.644Z","updated_at":"2026-04-06T00:11:28.277Z","avatar_url":"https://github.com/benoitpetit.png","language":"Go","funding_links":["https://liberapay.com/devbyben/donate"],"categories":[],"sub_categories":[],"readme":"# xsh — Twitter/X CLI\n\n[![Go Version](https://img.shields.io/badge/go-1.24+-00ADD8?style=flat-square\u0026logo=go)](https://golang.org/)\n[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)\n[![MCP](https://img.shields.io/badge/MCP-Compatible-green?style=flat-square)](https://modelcontextprotocol.io/)\n\nA fast, feature-complete command-line interface for Twitter/X, written in Go.  \nNo API keys required — authenticates directly via browser cookies.\n\n![xshwall](xsh_wall.png)\n\n---\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Authentication](#authentication)\n- [Commands](#commands)\n  - [Tweet Operations](#tweet-operations)\n  - [Timeline \u0026 Search](#timeline--search)\n  - [Users](#users)\n  - [Social Actions](#social-actions)\n  - [Bookmarks](#bookmarks)\n  - [Direct Messages](#direct-messages)\n  - [Lists](#lists)\n  - [Scheduled Tweets](#scheduled-tweets)\n  - [Trends](#trends)\n  - [Jobs](#jobs)\n  - [Media Download](#media-download)\n  - [Compose Thread](#compose-thread)\n  - [Export](#export)\n  - [Batch Operations](#batch-operations)\n  - [Character Count](#character-count)\n- [Output Formats](#output-formats)\n- [MCP Server](#mcp-server)\n- [Configuration](#configuration)\n- [Endpoint Management](#endpoint-management)\n- [Diagnostics \u0026 Status](#diagnostics--status)\n- [Development](#development)\n\n---\n\n## Features\n\n- **Zero API keys** — cookie-based authentication extracted from your browser\n- **AI-ready** — built-in MCP server compatible with Claude, Cursor, and any MCP client\n- **Multi-account** — manage and switch between multiple Twitter/X accounts\n- **Structured output** — JSON, YAML, and compact modes for scripting and agents\n- **Auto-updating endpoints** — dynamically discovers GraphQL operation IDs from X.com JS bundles\n- **Media support** — post up to 4 images per tweet, download media from any tweet\n- **Full coverage** — tweets, DMs, lists, bookmarks, jobs, trends, schedule, and more\n\n---\n\n## Installation\n\n### Using `go install` (Recommended)\n\nRequires [Go 1.24+](https://go.dev/doc/install):\n\n```bash\ngo install github.com/benoitpetit/xsh@latest\n```\n\n### Using Install Script\n\n**Linux/macOS:**\n```bash\ncurl -sSL https://raw.githubusercontent.com/benoitpetit/xsh/master/scripts/install.sh | bash\n```\n\n**Windows (PowerShell as Administrator):**\n```powershell\niwr -useb https://raw.githubusercontent.com/benoitpetit/xsh/master/scripts/install.ps1 | iex\n```\n\n### Pre-built Binaries\n\nDownload from [Releases](https://github.com/benoitpetit/xsh/releases):\n\n```bash\n# Linux (amd64)\ncurl -L https://github.com/benoitpetit/xsh/releases/latest/download/xsh-linux-amd64 -o xsh \u0026\u0026 \\\nchmod +x xsh \u0026\u0026 \\\nsudo mv xsh /usr/local/bin/\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/benoitpetit/xsh\ncd xsh\ngo build -o xsh .\nsudo mv xsh /usr/local/bin/\n```\n\n---\n\n## Quick Start\n\n```bash\n# 1. Authenticate (extracts cookies from your browser)\nxsh auth login\n\n# 2. View your timeline\nxsh feed\n\n# 3. Post a tweet\nxsh tweet post \"Hello from xsh!\"\n\n# 4. Search tweets\nxsh search \"golang\" --pages 2\n\n# 5. View a user profile\nxsh user elonmusk\n```\n\n---\n\n## Authentication\n\n### Automatic Browser Extraction\n\n```bash\n# Auto-detect browser (Chrome, Firefox, Brave, Edge, Chromium)\nxsh auth login\n\n# Target a specific browser\nxsh auth login --browser firefox\nxsh auth login --browser brave\n\n# Save under a named account\nxsh auth login --account work\n```\n\n### Manual / Import\n\n```bash\n# Import from Cookie Editor JSON export\nxsh auth import cookies.json\nxsh auth import cookies.json --account work\n\n# Set credentials manually\nxsh auth set\n\n# Check authentication status\nxsh auth status\n\n# Show current user info\nxsh auth whoami\n\n# List all stored accounts\nxsh auth accounts\n\n# Switch default account\nxsh auth switch work\n\n# Remove stored credentials\nxsh auth logout\n```\n\n\u003e Shortcuts `xsh accounts`, `xsh switch \u003cname\u003e`, and `xsh import \u003cfile\u003e` are also available at root level.\n\n---\n\n## Commands\n\n### Global Flags\n\nThese flags apply to every command:\n\n| Flag               | Short | Description                   |\n| ------------------ | ----- | ----------------------------- |\n| `--account \u003cname\u003e` |       | Use a specific stored account |\n| `--json`           |       | Output as JSON                |\n| `--yaml`           |       | Output as YAML                |\n| `--compact`        | `-c`  | Compact output for AI agents  |\n| `--verbose`        | `-v`  | Show HTTP requests (debug)    |\n\n---\n\n### Tweet Operations\n\n```bash\n# View a tweet (with optional thread tree)\nxsh tweet view \u003cid\u003e\nxsh tweet view \u003cid\u003e --thread\nxsh tweet view \u003cid\u003e --count 50\n\n# Post a tweet\nxsh tweet post \"Hello world!\"\nxsh tweet post \"With image\" --image photo.jpg\nxsh tweet post \"Multiple images\" -i img1.jpg -i img2.jpg -i img3.jpg\nxsh tweet post \"Reply\" --reply-to \u003ctweet-id\u003e\nxsh tweet post \"Quote\" --quote https://x.com/user/status/\u003cid\u003e\n\n# Delete your tweet\nxsh tweet delete \u003cid\u003e\n\n# Like / unlike\nxsh tweet like \u003cid\u003e\nxsh tweet unlike \u003cid\u003e\n\n# Retweet / undo\nxsh tweet retweet \u003cid\u003e\nxsh tweet unretweet \u003cid\u003e\n\n# Bookmark / remove\nxsh tweet bookmark \u003cid\u003e\nxsh tweet unbookmark \u003cid\u003e\n```\n\n**Shortcuts** available at root level:\n\n```bash\nxsh unlike \u003cid\u003e\nxsh unretweet \u003cid\u003e\nxsh unbookmark \u003cid\u003e\n```\n\n---\n\n### Timeline \u0026 Search\n\n```bash\n# Home timeline\nxsh feed\nxsh feed --type following              # Following timeline\nxsh feed --count 50 --pages 3         # 150 tweets total\nxsh feed --filter top --top 20        # Top 20 by engagement\nxsh feed --filter score --threshold 100\nxsh feed --cursor \u003ccursor\u003e            # Paginate\n\n# Search\nxsh search \"golang\"\nxsh search \"golang\" --type Latest     # Types: Top, Latest, Photos, Videos\nxsh search \"golang\" --count 50 --pages 2\nxsh search \"golang\" --cursor \u003ccursor\u003e\n```\n\n---\n\n### Users\n\n```bash\n# View profile\nxsh user \u003chandle\u003e\n\n# User's tweets\nxsh user tweets \u003chandle\u003e\nxsh user tweets \u003chandle\u003e --replies   # Include replies\nxsh user tweets \u003chandle\u003e --count 50\n\n# Liked tweets\nxsh user likes \u003chandle\u003e --count 30\n\n# Followers / following\nxsh user followers \u003chandle\u003e --count 50\nxsh user following \u003chandle\u003e --count 50\n```\n\n---\n\n### Social Actions\n\n```bash\n# Follow / unfollow\nxsh follow \u003chandle\u003e\nxsh unfollow \u003chandle\u003e\n\n# Block / unblock\nxsh block \u003chandle\u003e\nxsh unblock \u003chandle\u003e\n\n# Mute / unmute\nxsh mute \u003chandle\u003e\nxsh unmute \u003chandle\u003e\n```\n\n---\n\n### Bookmarks\n\n```bash\n# View all bookmarks\nxsh bookmarks\nxsh bookmarks --count 50\n\n# List bookmark folders\nxsh bookmarks-folders\n\n# View tweets in a specific folder\nxsh bookmarks-folder \u003cfolder-id\u003e\n```\n\n---\n\n### Direct Messages\n\n```bash\n# View inbox\nxsh dm inbox\n\n# Send a DM\nxsh dm send \u003chandle\u003e \"Your message\"\n\n# Delete a DM message\nxsh dm delete \u003cmessage-id\u003e\n```\n\n---\n\n### Lists\n\n```bash\n# View all your lists\nxsh lists\n\n# View tweets from a list\nxsh lists view \u003clist-id\u003e\nxsh lists view \u003clist-id\u003e --count 50\n\n# Create / delete a list\nxsh lists create \"List name\"\nxsh lists delete \u003clist-id\u003e\n\n# Manage members\nxsh lists members \u003clist-id\u003e\nxsh lists add-member \u003clist-id\u003e \u003chandle\u003e\nxsh lists remove-member \u003clist-id\u003e \u003chandle\u003e\n\n# Pin / unpin\nxsh lists pin \u003clist-id\u003e\nxsh lists unpin \u003clist-id\u003e\n```\n\n---\n\n### Scheduled Tweets\n\n```bash\n# Schedule a tweet\nxsh schedule \"My future tweet\" --at \"2026-04-01 09:00\"\n\n# List scheduled tweets\nxsh scheduled\n\n# Cancel a scheduled tweet\nxsh unschedule \u003cscheduled-tweet-id\u003e\n```\n\n---\n\n### Trends\n\n```bash\n# Worldwide trends\nxsh trends\n\n# By location name\nxsh trends --location \"Paris\"\nxsh trends --location \"France\"\n\n# By WOEID\nxsh trends --woeid 1        # Worldwide\nxsh trends --woeid 615702   # Paris\n```\n\n---\n\n### Jobs\n\n```bash\n# Search job listings\nxsh jobs search \"software engineer\"\nxsh jobs search \"data engineer\" --location \"Paris\"\nxsh jobs search \"devops\" --location-type remote\nxsh jobs search \"backend\" --employment-type full_time\nxsh jobs search \"intern\" --seniority entry_level\nxsh jobs search \"manager\" --company Google --pages 2\n\n# Available filters:\n#   --location \u003ccity/country\u003e\n#   --location-type  remote | onsite | hybrid\n#   --employment-type  full_time | part_time | contract | internship\n#   --seniority  entry_level | mid_level | senior\n#   --company \u003cname\u003e\n#   --industry \u003csector\u003e\n#   --count \u003cn\u003e  (default 25)\n#   --pages \u003cn\u003e  (default 1)\n\n# View job details\nxsh jobs view \u003cjob-id\u003e\n```\n\n---\n\n### Media Download\n\n```bash\n# Download all media from a tweet\nxsh download \u003ctweet-id\u003e\nxsh download \u003ctweet-id\u003e --output-dir ./media\n```\n\n---\n\n### Compose Thread\n\n```bash\n# Interactive mode (prompts for each tweet)\nxsh compose\n\n# From a text file (auto-splits into thread)\nxsh compose --file thread.txt\n\n# From stdin\ncat thread.txt | xsh compose\n\n# Preview without posting\nxsh compose --file thread.txt --dry-run\n```\n\n---\n\n### Export\n\nExport tweets to file in multiple formats: `json`, `jsonl`, `csv`, `tsv`, `md`.\n\n```bash\n# Export timeline\nxsh export feed --format csv --output timeline.csv\nxsh export feed --format jsonl --output tweets.jsonl --count 200\nxsh export feed --type following --filter top\n\n# Export search results\nxsh export search \"golang\" --format md --output results.md\n\n# Export bookmarks\nxsh export bookmarks --format json --output bookmarks.json\n\n# Write to stdout\nxsh export feed --format jsonl --output -\n```\n\n---\n\n### Batch Operations\n\n```bash\n# Fetch multiple tweets by ID\nxsh tweets \u003cid1\u003e \u003cid2\u003e \u003cid3\u003e\n\n# Fetch multiple user profiles\nxsh users \u003chandle1\u003e \u003chandle2\u003e \u003chandle3\u003e\n```\n\n---\n\n### Character Count\n\n```bash\n# Count characters in text\nxsh count \"My tweet draft\"\n\n# From a file\nxsh count --file draft.txt\n\n# From stdin\necho \"My tweet\" | xsh count\n\n# Show formatted preview\nxsh count \"My tweet\" --preview\nxsh count --file draft.txt --preview --width 80\n```\n\n---\n\n## Output Formats\n\nAll commands support structured output for scripting and AI integration:\n\n```bash\n# JSON\nxsh feed --json\nxsh user elonmusk --json\n\n# YAML\nxsh search \"golang\" --yaml\n\n# Compact (essential fields only, ideal for AI agents)\nxsh feed --compact\n\n# Pipe auto-detection: JSON is used automatically when stdout is not a TTY\nxsh feed | jq '.[] | .text'\n\n# Use a specific account\nxsh feed --account work\n```\n\n---\n\n## MCP Server\n\nxsh includes a full [Model Context Protocol](https://modelcontextprotocol.io/) server for use with Claude, Cursor, and other MCP-compatible AI clients.\n\n```bash\nxsh mcp\n```\n\n### Claude Desktop Configuration\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"xsh\": {\n      \"command\": \"xsh\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n### Available MCP Tools\n\n| Category   | Tools                                                                                                                                                      |\n| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Timeline   | `get_feed`, `get_home_latest_timeline`                                                                                                                     |\n| Search     | `search`, `search_bookmarks`                                                                                                                               |\n| Tweets     | `get_tweet`, `get_tweet_thread`, `post_tweet`, `delete_tweet`, `get_tweets_batch`                                                                          |\n| Engagement | `like`, `unlike`, `retweet`, `unretweet`, `bookmark`, `unbookmark`                                                                                         |\n| Users      | `get_user`, `get_users_batch`, `get_user_tweets`, `get_user_likes`, `get_followers`, `get_following`                                                       |\n| Social     | `follow`, `unfollow`, `block`, `unblock`, `mute`, `unmute`                                                                                                 |\n| Bookmarks  | `list_bookmarks`, `get_bookmark_folders`, `get_bookmark_folder`                                                                                            |\n| Lists      | `get_user_lists`, `get_list_timeline`, `get_list_members`, `create_list`, `delete_list`, `add_list_member`, `remove_list_member`, `pin_list`, `unpin_list` |\n| DMs        | `dm_inbox`, `send_dm`, `delete_dm`                                                                                                                         |\n| Scheduled  | `schedule_tweet`, `get_scheduled_tweets`, `delete_scheduled_tweet`                                                                                         |\n| Trends     | `get_trending`                                                                                                                                             |\n| Jobs       | `search_jobs`, `get_job`                                                                                                                                   |\n| Media      | `download_media`, `upload_media`                                                                                                                           |\n| Compose    | `compose_thread`                                                                                                                                           |\n| Utils      | `count_characters`, `export_tweets`                                                                                                                        |\n| Endpoints  | `get_endpoints`, `refresh_endpoints`                                                                                                                       |\n\n---\n\n## Configuration\n\nConfiguration is stored at `~/.config/xsh/config.toml`:\n\n```bash\n# Show current configuration\nxsh config\nxsh config show\n\n# Get a specific value\nxsh config get filter.likes_weight\n\n# Set a value\nxsh config set display.theme dark\nxsh config set request.timeout 60\n\n# Open in editor\nxsh config edit\n\n# Show config file path\nxsh config path\n\n# Reset to defaults\nxsh config reset\n```\n\n### Example `config.toml`\n\n```toml\ndefault_count = 20\n\n[display]\ntheme           = \"default\"\nshow_engagement = true\nshow_timestamps = true\nmax_width       = 100\n\n[request]\ndelay       = 1.5\ntimeout     = 30\nmax_retries = 3\n\n[filter]\nlikes_weight     = 1.0\nretweets_weight  = 1.5\nreplies_weight   = 0.5\nbookmarks_weight = 2.0\nviews_log_weight = 0.3\nmin_score        = 0\n```\n\n---\n\n## Endpoint Management\n\nxsh dynamically discovers GraphQL operation IDs from X.com's JavaScript bundles and caches them locally.\n\n```bash\n# List all cached endpoints\nxsh endpoints list\n\n# Check status of a specific endpoint\nxsh endpoints check HomeTimeline\n\n# Refresh endpoints from X.com (no auth required)\nxsh endpoints refresh\n\n# Show endpoint system status\nxsh endpoints status\n\n# Manually update a single endpoint\nxsh endpoints update \u003coperation\u003e \u003cendpoint-id\u003e\n\n# Reset all endpoints to bundled defaults\nxsh endpoints reset\n\n# Auto-update obsolete endpoints (safe, no auth needed)\nxsh auto-update\nxsh auto-update --dry-run   # Check only, don't update\nxsh auto-update --force     # Force refresh (ignore cache)\n```\n\n---\n\n## Diagnostics \u0026 Status\n\n```bash\n# System status: auth, endpoints, cache health\nxsh status\nxsh status --check   # Run fresh endpoint health check\nxsh status --json\n\n# Full diagnostic report\nxsh doctor\n\n# Print version\nxsh version\n```\n\n---\n\n## Development\n\n```bash\n# Clone\ngit clone https://github.com/benoitpetit/xsh\ncd xsh\n\n# Build\ngo build -o xsh .\n\n# Run tests\ngo test ./tests/...\n\n# Build with version info\ngo build -ldflags \"-X main.Version=1.0.0\" -o xsh .\n```\n\n### Project Structure\n\n```\ncore/\n├── main.go           # Entry point\n├── cmd/              # Cobra CLI commands\n├── core/             # API client, auth, config, endpoints\n├── models/           # Tweet, User, DM, etc.\n├── display/          # Terminal formatters\n├── utils/            # Helpers (filter, validation, article, delay, hash)\n├── browser/          # Browser cookie extraction\n└── tests/            # Integration tests\n```\n\n### Requirements\n\n- Go 1.24+\n- A Twitter/X account\n- A supported browser (for cookie extraction)\n\n---\n\n## Security\n\n- Credentials stored locally with `0600` permissions\n- No data sent to third parties — direct API calls to X/Twitter only\n- TLS fingerprinting (uTLS) to avoid bot detection\n- Cookie values sanitized per RFC 6265 before use\n\n---\n\n## About\n\n**xsh** is a complete rewrite in Go of the original [clix](https://github.com/spideystreet/clix) Python project. This is not a fork — it is a ground-up reimplementation with a focus on performance, reliability, and modern Go practices.\n\n---\n\n## License\n\n[MIT](LICENSE)\n\n---\n\n**Made with ❤️ and Go**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitpetit%2Fxsh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenoitpetit%2Fxsh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitpetit%2Fxsh/lists"}