{"id":31037020,"url":"https://github.com/stanleymasinde/twitter","last_synced_at":"2026-02-28T18:14:55.198Z","repository":{"id":312781626,"uuid":"1048064274","full_name":"StanleyMasinde/twitter","owner":"StanleyMasinde","description":"Tweet without going to twitter.com","archived":false,"fork":false,"pushed_at":"2025-09-09T19:34:59.000Z","size":218,"stargazers_count":14,"open_issues_count":1,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-09T23:22:39.574Z","etag":null,"topics":["clap-rs","cli","rust","twitter-api"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/StanleyMasinde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2025-08-31T20:46:30.000Z","updated_at":"2025-09-09T19:35:03.000Z","dependencies_parsed_at":"2025-09-02T01:15:10.563Z","dependency_job_id":"fcc0e4a6-80ba-450d-9dc6-42b1014f8104","html_url":"https://github.com/StanleyMasinde/twitter","commit_stats":null,"previous_names":["stanleymasinde/twitter"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/StanleyMasinde/twitter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StanleyMasinde%2Ftwitter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StanleyMasinde%2Ftwitter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StanleyMasinde%2Ftwitter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StanleyMasinde%2Ftwitter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StanleyMasinde","download_url":"https://codeload.github.com/StanleyMasinde/twitter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StanleyMasinde%2Ftwitter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275062969,"owners_count":25398888,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["clap-rs","cli","rust","twitter-api"],"created_at":"2025-09-14T04:46:04.307Z","updated_at":"2026-02-28T18:14:55.188Z","avatar_url":"https://github.com/StanleyMasinde.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Twitter CLI\n\u003e Tweet without going to twitter.com\n\n\n![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/StanleyMasinde/twitter/total)\n[![Build and test](https://github.com/StanleyMasinde/twitter/actions/workflows/rust.yml/badge.svg)](https://github.com/StanleyMasinde/twitter/actions/workflows/rust.yml)\n\n## What it does\nI love creating content on Twitter but twitter.com leads to doomscrolling. This is my way of fighting that.\n\nSimple CLI for posting to Twitter using their API v2. No OAuth flow - just configure once and tweet.\n\n## Installation\n\n### Quick install\nInstall the latest version with the following command. If you prefer, review the script first.\n\n```shell\ncurl -fsSL https://raw.githubusercontent.com/StanleyMasinde/twitter/main/install.sh | sh\n```\nThis will automatically\n- Detect your operating system and architecture\n- Download the correct binary\n- Verify the SHA256 checksum for security\n- Install to /usr/local/bin\n- Clean up temporary files\n\nReview the installer before running:\n```shell\ncurl -fsSL https://raw.githubusercontent.com/StanleyMasinde/twitter/main/install.sh\n```\n\n### Install a specific version\n```shell\ncurl -fsSL https://raw.githubusercontent.com/StanleyMasinde/twitter/main/install.sh | sh -s v1.5.0\n```\n\n### Custom install location\n```shell\ncurl -fsSL https://raw.githubusercontent.com/StanleyMasinde/twitter/main/install.sh | TWITTER_INSTALL=~/.local/bin sh\n```\n\n### Updating\n```shell\nsudo twitter update\n```\n`twitter update` downloads the latest release, writes a temporary binary in the install directory, then atomically replaces the current executable.  \nIf `twitter` is installed in `/usr/local/bin` (default install location), that directory is root-owned, so updating requires elevated privileges.\n\nIf you installed to a user-writable location (for example with `TWITTER_INSTALL=~/.local/bin`), `sudo` is not required.\n\nOn Windows, run:\n```powershell\ntwitter update\n```\n`twitter update` schedules replacement of the current `twitter.exe` after the running process exits. Run an elevated terminal only if the executable is in a protected directory (for example `C:\\Program Files`).\n\n### ArchLinux\nArchLinux users can install the community maintained AUR binary [package](https://aur.archlinux.org/packages/twitter-cli) using yay or any other AUR helper:\n```bash\nyay -S twitter-cli\n```\n\u003e[!WARNING]\n\u003e The AUR package is managed by the community. \n\u003e Please use the install script for other Unix based systems.\n\nAfter installation the executable is available as `twitter`\n\nYou can also download the appropriate binary for your machine from [releases](https://github.com/StanleyMasinde/twitter/releases/latest):\n\n### Windows x64 Via PowerShell\n\u003e Administrator privileges are only needed when writing to a protected directory.\n\u003e Ensure your default shell is PowerShell. If you are not sure, search for PowerShell and run it.\n```powershell\n# Download and extract\nInvoke-WebRequest -Uri https://github.com/StanleyMasinde/twitter/releases/latest/download/twitter-windows-x86_64.zip -OutFile twitter.zip\nExpand-Archive -Force twitter.zip -DestinationPath .\n\n# Move exe to a user bin directory\n$dest = \"$env:USERPROFILE\\bin\"\nNew-Item -ItemType Directory -Force -Path $dest | Out-Null\nMove-Item -Force \".\\twitter.exe\" \"$dest\\twitter.exe\"\n\n# Add bin directory to PATH (persistent, per-user)\n$old = [Environment]::GetEnvironmentVariable(\"Path\",\"User\")\nif ($old -notlike \"*$dest*\") {\n  [Environment]::SetEnvironmentVariable(\"Path\",\"$old;$dest\",\"User\")\n}\n\n# Make it available in this session\n$env:Path += \";$dest\"\n```\n\n\u003e[!NOTE]\n\u003e For the CLI to run on Windows, ensure you have installed the latest C++ [redistributable runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-supported-redistributable-version) for your architecture.\n\u003e After that installation, open the Windows Terminal and use Twitter CLI by typing twitter. \n\n## Configuration\n1. Create a Twitter developer account at [developer.twitter.com](https://developer.twitter.com)\n2. Create a new app and get your API credentials\n\n### Interactive Setup (Recommended)\n\u003e [!WARNING]\n\u003e This will override your existing config. Only run it on setup.\n\n```bash\ntwitter config --init\n```\n\n### Quick Edit\n```bash\ntwitter config --edit\n```\nOpens your default editor (`$EDITOR`) with the config file. Creates `~/.config/twitter_cli/config.toml` if it doesn't exist.\n\nExpected format:\n```toml\n# The account that will be used to tweet\n# Please note, current account uses 0 based index.\n# This means the first account is 0\ncurrent_account = 0\n\n# Account 1\n[[accounts]]\nconsumer_key = \"your_consumer_key\"\nconsumer_secret = \"your_consumer_secret\"\naccess_token = \"your_access_token\"\naccess_secret = \"your_access_secret\"\nbearer_token = \"your_bearer_token\"\n\n# Account 2\n[[accounts]]\nconsumer_key = \"your_consumer_key\"\nconsumer_secret = \"your_consumer_secret\"\naccess_token = \"your_access_token\"\naccess_secret = \"your_access_secret\"\nbearer_token = \"your_bearer_token\"\n```\n\n### Manual Configuration\nCreate config file at `~/.config/twitter_cli/config.toml` with the format above. Keep this file private since it contains API secrets.\n\n### Validation\n```bash\ntwitter config --show # Visual preview\ntwitter config --validate # Check for issues\n```\n\n## Update App Permissions\nIf you face a 403 error when tweeting:\n\n1. In the Twitter Developer Portal, go to your App → **User authentication settings**\n2. Set **App permissions** to **Read and write**\n3. Save changes, then regenerate your Access Token \u0026 Secret\n4. Update your config with the new values\n\n\u003e **NB:** Regenerate tokens after updating permissions, otherwise old tokens remain read-only.\n\n## Usage\n\n### Tweet in CLI Mode\n#### Tweet\n```bash\ntwitter tweet --body \"Building something cool today\"\n```\n\n#### Piped input\n```bash\necho \"I love CLIs\" | twitter tweet\n```\n#### From text files\n```bash\ncat drafts.txt | twitter tweet\n```\n#### Edit tweet in an editor\nOmit --body and it will launch your default terminal editor. Like Vim or Nano.\n```bash\ntwitter tweet\n```\n\n#### Add Media\nThe parameter is image because I do not see the point of uploading video from the terminal.\n```bash\ntwitter tweet --image ~/Downloads/image.png\n```\n\n### Tweet a thread\nThreads are created whenever input contains `---` separators, regardless of input mode.\n```bash\ntwitter tweet --editor\n```\nThis will launch your default terminal editor. Separate your threads with --- like this.\n```txt\nThis is a very long thread. This being the intro.\n---\nThe three dashes indicate the boundary between tweets so this will be tweet 2.\n---\nThis will be tweet 3\n```\n\n#### Thread via stdin\nPipe thread content with `---` separators.\n```bash\ncat thread.txt | twitter tweet\n```\n\n### Schedule tweets\n#### Add a scheduled tweet\nUse either `--on` or `--at`.\n```bash\ntwitter schedule new --body \"Ship update at 5:06pm\" --at \"17:06\"\ntwitter schedule new --body \"Ship update on Tuesday\" --on \"Tuesday\"\n```\n\n#### List scheduled tweets\n```bash\ntwitter schedule list\ntwitter schedule list --filter failed\ntwitter schedule list --filter sent\n```\nIf no rows match your filter, the CLI prints:\n```text\nNo scheduled tweets were found.\n```\n\n#### Run pending scheduled tweets\n```bash\ntwitter schedule run\n```\nIf none are due, the CLI prints:\n```text\nNo pending scheduled tweets to run.\n```\n\n#### Pair with your OS scheduler\n`schedule run` is intended to be executed regularly by your OS scheduler.\nRun scheduler jobs as the same user who ran `twitter config --init`.\nFirst get your installed binary path:\n```bash\ncommand -v twitter\n```\n\nLinux (cron):\n```bash\ncrontab -e\n```\n```cron\n* * * * * /usr/local/bin/twitter schedule run \u003e\u003e /tmp/twitter-schedule.log 2\u003e\u00261\n```\nIf your binary is not in `/usr/local/bin/twitter`, replace that path with the output of `command -v twitter`.\n\nmacOS (launchd):\n```xml\n\u003c!-- ~/Library/LaunchAgents/com.twitter.schedule.plist --\u003e\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n  \u003cdict\u003e\n    \u003ckey\u003eLabel\u003c/key\u003e\u003cstring\u003ecom.twitter.schedule\u003c/string\u003e\n    \u003ckey\u003eProgramArguments\u003c/key\u003e\n    \u003carray\u003e\n      \u003cstring\u003e/usr/local/bin/twitter\u003c/string\u003e\n      \u003cstring\u003eschedule\u003c/string\u003e\n      \u003cstring\u003erun\u003c/string\u003e\n    \u003c/array\u003e\n    \u003ckey\u003eStartInterval\u003c/key\u003e\u003cinteger\u003e60\u003c/integer\u003e\n    \u003ckey\u003eStandardOutPath\u003c/key\u003e\u003cstring\u003e/tmp/twitter-schedule.log\u003c/string\u003e\n    \u003ckey\u003eStandardErrorPath\u003c/key\u003e\u003cstring\u003e/tmp/twitter-schedule.log\u003c/string\u003e\n  \u003c/dict\u003e\n\u003c/plist\u003e\n```\nIf your binary is not in `/usr/local/bin/twitter`, replace that path with the output of `command -v twitter`.\nLoad it (current user):\n```bash\nlaunchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.twitter.schedule.plist\nlaunchctl kickstart -k gui/$(id -u)/com.twitter.schedule\n```\n\nWindows (Task Scheduler):\nUse `where twitter` in PowerShell to find the full path to `twitter.exe`.\n\nCreate a task that runs every minute with:\n```powershell\nschtasks /Create /SC MINUTE /MO 1 /TN \"TwitterScheduleRunner\" /TR \"\\\"C:\\Users\\\u003cyou\u003e\\bin\\twitter.exe\\\" schedule run\" /F\n```\nIf your binary is not in `C:\\Users\\\u003cyou\u003e\\bin\\twitter.exe`, replace that path with the output of `where twitter`.\n\n#### Clear scheduled tweets\n```bash\ntwitter schedule clear\n```\nThe CLI prints how many records were removed, for example:\n```text\nCleared 3 scheduled tweets.\n```\n\n**API Response:**\n```text\nTweet Id: 2006409743426818416\nTweet body: Hello, world\n```\n\n## Show usage\nYou can show the API usage via the usage subcommand.\n```shell\ntwitter usage\n```\nThe above command will show the API usage like the one below.\n```text\nDaily project usage: 0/100\n```\n\n## Tech Stack\n- Rust\n- Twitter API v2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstanleymasinde%2Ftwitter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstanleymasinde%2Ftwitter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstanleymasinde%2Ftwitter/lists"}