โ† All skills
Tencent SkillHub ยท Developer Tools

X Twitter

X/Twitter manager: post, reply, search, like, retweet & get analytics. Requires: powershell/pwsh. Reads ~/.config/x-twitter/credentials.json (X_API_KEY, X_AP...

skill openclawclawhub Free
0 Downloads
0 Stars
0 Installs
0 Score
High Signal

X/Twitter manager: post, reply, search, like, retweet & get analytics. Requires: powershell/pwsh. Reads ~/.config/x-twitter/credentials.json (X_API_KEY, X_AP...

โฌ‡ 0 downloads โ˜… 0 stars Unverified but indexed

Install for OpenClaw

Quick setup
  1. Download the package from Yavira.
  2. Extract the archive and review SKILL.md first.
  3. Import or place the package into your OpenClaw setup.

Requirements

Target platform
OpenClaw
Install method
Manual import
Extraction
Extract archive
Prerequisites
OpenClaw
Primary doc
SKILL.md

Package facts

Download mode
Yavira redirect
Package format
ZIP package
Source platform
Tencent SkillHub
What's included
SKILL.md, _meta.json

Validation

  • Use the Yavira download entry.
  • Review SKILL.md after the package is downloaded.
  • Confirm the extracted package contains the expected setup assets.

Install with your agent

Agent handoff

Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.

  1. Download the package from Yavira.
  2. Extract it into a folder your agent can access.
  3. Paste one of the prompts below and point your agent at the extracted folder.
New install

I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.

Upgrade existing

I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.

Trust & source

Release facts

Source
Tencent SkillHub
Verification
Indexed source record
Version
1.0.2

Documentation

ClawHub primary doc Primary doc: SKILL.md 12 sections Open source page

x-twitter - Universal X/Twitter API Skill

Constructs and executes X API v2 calls inline based on what the user wants. No scripts needed. API version: v2 Base URL: https://api.twitter.com/2 Requires an X Developer App with OAuth 1.0a User Context credentials. Free tier supports posting, reading own timeline, and basic lookups. Elevated/Pro tier required for search and higher rate limits.

STEP 1 - Load Credentials

Credentials are stored in ~/.config/x-twitter/credentials.json. $cfg = Get-Content "$HOME/.config/x-twitter/credentials.json" -Raw | ConvertFrom-Json $apiKey = $cfg.X_API_KEY $apiSecret = $cfg.X_API_SECRET $accessToken = $cfg.X_ACCESS_TOKEN $accessSecret = $cfg.X_ACCESS_SECRET If the file does not exist, guide setup. Required fields: FieldPurposeX_API_KEYApp API Key (Consumer Key) - from X Developer PortalX_API_SECRETApp API Secret (Consumer Secret) - from X Developer PortalX_ACCESS_TOKENAccount Access Token - from X Developer PortalX_ACCESS_SECRETAccount Access Token Secret - from X Developer Portal One-time setup: Go to X Developer Portal Create a Project and App (or use existing) Under App Settings -> User authentication settings: enable OAuth 1.0a with Read and Write permissions Go to App Keys and Tokens -> Generate Access Token and Secret (for your own account) Save all four values: @{ X_API_KEY = "your_api_key" X_API_SECRET = "your_api_secret" X_ACCESS_TOKEN = "your_access_token" X_ACCESS_SECRET = "your_access_token_secret" } | ConvertTo-Json | Set-Content "$HOME/.config/x-twitter/credentials.json" -Encoding UTF8 Restrict file permissions immediately after saving: # Windows icacls "$HOME/.config/x-twitter/credentials.json" /inheritance:r /grant:r "$($env:USERNAME):(R,W)" # macOS / Linux # chmod 600 ~/.config/x-twitter/credentials.json Never commit this file to version control. It contains long-lived secrets. Rotate X_ACCESS_TOKEN and X_ACCESS_SECRET periodically and immediately if the host is ever compromised. X_API_KEY and X_API_SECRET are app-level credentials - keep them permanently but treat as sensitive. This skill makes no external calls other than to api.twitter.com. No data is forwarded to third parties.

STEP 2 - Figure Out the API Call

X API v2 uses OAuth 1.0a for user-context actions (post, delete, like, retweet) and Bearer Token for read-only public data. This skill uses OAuth 1.0a for all calls (covers both read and write).

OAuth 1.0a Signing Helper

All requests require an OAuth 1.0a Authorization header. Use this helper: function Get-OAuthHeader { param($method, $url, $apiKey, $apiSecret, $accessToken, $accessSecret, [hashtable]$params = @{}) $nonce = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes([System.Guid]::NewGuid().ToString("N"))) $timestamp = [int][double]::Parse(([datetime]::UtcNow - [datetime]"1970-01-01").TotalSeconds) $oauthParams = @{ oauth_consumer_key = $apiKey oauth_nonce = $nonce oauth_signature_method = "HMAC-SHA1" oauth_timestamp = $timestamp oauth_token = $accessToken oauth_version = "1.0" } # Merge all params for signature base $allParams = @{} $oauthParams.GetEnumerator() | ForEach-Object { $allParams[$_.Key] = $_.Value } $params.GetEnumerator() | ForEach-Object { $allParams[$_.Key] = $_.Value } # Build signature base string $sortedParams = ($allParams.GetEnumerator() | Sort-Object Key | ForEach-Object { "$([Uri]::EscapeDataString($_.Key))=$([Uri]::EscapeDataString($_.Value))" }) -join "&" $baseString = "$method&$([Uri]::EscapeDataString($url))&$([Uri]::EscapeDataString($sortedParams))" # Sign $signingKey = "$([Uri]::EscapeDataString($apiSecret))&$([Uri]::EscapeDataString($accessSecret))" $hmac = New-Object System.Security.Cryptography.HMACSHA1 $hmac.Key = [System.Text.Encoding]::ASCII.GetBytes($signingKey) $signature = [System.Convert]::ToBase64String($hmac.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($baseString))) $oauthParams["oauth_signature"] = $signature # Build header $headerParts = $oauthParams.GetEnumerator() | Sort-Object Key | ForEach-Object { "$([Uri]::EscapeDataString($_.Key))=`"$([Uri]::EscapeDataString($_.Value))`"" } return "OAuth $($headerParts -join ', ')" }

Common Endpoints

What user wantsMethodEndpointPost a tweetPOST/tweets body: textReply to a tweetPOST/tweets body: text + reply.in_reply_to_tweet_idQuote a tweetPOST/tweets body: text + quote_tweet_idDelete a tweetDELETE/tweets/{id}Like a tweetPOST/users/{id}/likes body: tweet_idUnlike a tweetDELETE/users/{id}/likes/{tweet_id}RetweetPOST/users/{id}/retweets body: tweet_idUndo retweetDELETE/users/{id}/retweets/{tweet_id}Get own timelineGET/users/{id}/tweets?max_results=10&tweet.fields=created_at,public_metricsGet home timelineGET/users/{id}/timelines/reverse_chronological?max_results=10Search recent tweetsGET/tweets/search/recent?query=...&max_results=10Get tweet by IDGET/tweets/{id}?tweet.fields=created_at,public_metrics,author_idGet own user infoGET/users/me?user.fields=username,name,public_metrics,descriptionGet user by usernameGET/users/by/username/{username}?user.fields=public_metricsGet followersGET/users/{id}/followers?max_results=100Get followingGET/users/{id}/following?max_results=100Follow a userPOST/users/{id}/following body: target_user_idUnfollow a userDELETE/users/{id}/following/{target_id}Get mentionsGET/users/{id}/mentions?max_results=10&tweet.fields=created_at,author_idGet bookmarksGET/users/{id}/bookmarks?max_results=10Bookmark a tweetPOST/users/{id}/bookmarks body: tweet_idCreate a listPOST/lists body: name, privateGet own listsGET/users/{id}/owned_listsAdd member to listPOST/lists/{id}/members body: user_id

API Call Patterns

GET: $url = "https://api.twitter.com/2/ENDPOINT" $authHeader = Get-OAuthHeader -method "GET" -url $url -apiKey $apiKey -apiSecret $apiSecret -accessToken $accessToken -accessSecret $accessSecret $result = Invoke-RestMethod -Uri $url -Headers @{ Authorization = $authHeader } -ErrorAction Stop GET with query params (include in signature): $url = "https://api.twitter.com/2/tweets/search/recent" $qp = @{ query = "from:username"; max_results = "10" } $authHeader = Get-OAuthHeader -method "GET" -url $url -apiKey $apiKey -apiSecret $apiSecret -accessToken $accessToken -accessSecret $accessSecret -params $qp $qs = ($qp.GetEnumerator() | ForEach-Object { "$($_.Key)=$([Uri]::EscapeDataString($_.Value))" }) -join "&" $result = Invoke-RestMethod -Uri "$url`?$qs" -Headers @{ Authorization = $authHeader } -ErrorAction Stop POST (JSON body): $url = "https://api.twitter.com/2/tweets" $body = @{ text = "Hello from OpenClaw!" } | ConvertTo-Json $authHeader = Get-OAuthHeader -method "POST" -url $url -apiKey $apiKey -apiSecret $apiSecret -accessToken $accessToken -accessSecret $accessSecret $result = Invoke-RestMethod -Uri $url -Method POST -Headers @{ Authorization = $authHeader; "Content-Type" = "application/json" } -Body $body -ErrorAction Stop Write-Host "Posted tweet ID: $($result.data.id)" DELETE: $url = "https://api.twitter.com/2/tweets/{id}" $authHeader = Get-OAuthHeader -method "DELETE" -url $url -apiKey $apiKey -apiSecret $apiSecret -accessToken $accessToken -accessSecret $accessSecret $result = Invoke-RestMethod -Uri $url -Method DELETE -Headers @{ Authorization = $authHeader } -ErrorAction Stop

Get Own User ID (needed for user-context endpoints)

$url = "https://api.twitter.com/2/users/me" $authHeader = Get-OAuthHeader -method "GET" -url $url -apiKey $apiKey -apiSecret $apiSecret -accessToken $accessToken -accessSecret $accessSecret $me = Invoke-RestMethod -Uri $url -Headers @{ Authorization = $authHeader } -ErrorAction Stop $userId = $me.data.id

Post with Media (image attachment)

# Step 1: Upload media via v1.1 endpoint (media upload is not on v2 yet) $mediaUrl = "https://upload.twitter.com/1.1/media/upload.json" $fileBytes = [System.IO.File]::ReadAllBytes($imagePath) $b64 = [System.Convert]::ToBase64String($fileBytes) $uploadAuth = Get-OAuthHeader -method "POST" -url $mediaUrl -apiKey $apiKey -apiSecret $apiSecret -accessToken $accessToken -accessSecret $accessSecret $upload = Invoke-RestMethod -Uri $mediaUrl -Method POST -Headers @{ Authorization = $uploadAuth; "Content-Type" = "application/json" } ` -Body (@{ media_data = $b64 } | ConvertTo-Json) -ErrorAction Stop $mediaId = $upload.media_id_string # Step 2: Post tweet with media $tweetUrl = "https://api.twitter.com/2/tweets" $tweetAuth = Get-OAuthHeader -method "POST" -url $tweetUrl -apiKey $apiKey -apiSecret $apiSecret -accessToken $accessToken -accessSecret $accessSecret $result = Invoke-RestMethod -Uri $tweetUrl -Method POST ` -Headers @{ Authorization = $tweetAuth; "Content-Type" = "application/json" } ` -Body (@{ text = $caption; media = @{ media_ids = @($mediaId) } } | ConvertTo-Json -Depth 3) -ErrorAction Stop Write-Host "Posted tweet with media ID: $($result.data.id)"

STEP 3 - Handle Errors

try { # ... API call ... } catch { $err = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue $status = $_.Exception.Response.StatusCode.value__ $title = $err.title $detail = $err.detail Write-Host "HTTP $status - $title : $detail" } HTTP StatusTitle / CodeMeaningFix400Invalid RequestBad parameters or malformed JSONCheck required fields; ensure JSON body is valid401UnauthorizedInvalid or expired credentialsRegenerate Access Token and Secret in Developer Portal403ForbiddenApp lacks permission or write access disabledEnable Read and Write in App -> User authentication settings403duplicate-contentTweet text is a duplicateChange the tweet text429Too Many RequestsRate limit exceededCheck x-rate-limit-reset header; wait until reset time404Not FoundTweet or user does not existVerify the ID; tweet may have been deleted453Access to endpoint deniedEndpoint requires elevated access tierUpgrade to Basic/Pro at developer.twitter.com

Rate Limits (Free Tier)

ActionLimitPOST /tweets17 tweets per 24h per user; 50 per appDELETE /tweets50 per 15 minGET /users/me25 per 24hGET /tweets/search/recentRequires Basic tier or aboveGET timelines5 per 15 min (Free); 180 per 15 min (Basic) If rate limited: read the x-rate-limit-reset response header (Unix timestamp) and tell the user when they can retry.

Access Tiers

TierCostKey limitsFree$017 tweets/day write; very limited readBasic$100/month100 tweets/day; search; higher read limitsPro$5000/monthFull access; high rate limits

AGENT RULES

Always load credentials first. If missing or incomplete, guide setup. Always use OAuth 1.0a via the Get-OAuthHeader helper - never send raw tokens in query strings. Get own user ID first when calling user-context endpoints (/users/{id}/...) - use /users/me. Never embed tokens as literals - read all four credential fields fresh from disk at runtime. Rotate credentials if the host is ever compromised: regenerate Access Token and Secret in Developer Portal. Rate limits: on HTTP 429, read x-rate-limit-reset header and tell the user the exact retry time. Free tier restrictions: search requires Basic tier; if user gets 453 "Access to endpoint denied", tell them the required tier and link to developer.twitter.com/en/portal/products. Media upload: uses v1.1 upload endpoint (upload.twitter.com) - this is intentional and expected; it is still Twitter/X infrastructure. State this if the user asks. Least-privilege: instruct user to enable only Read and Write in app settings; do not request DM permissions unless explicitly needed. All API calls go to api.twitter.com and upload.twitter.com only - both are X/Twitter infrastructure. No external forwarding, no third-party services. Construct API calls inline from user intent - do not look for script files. On any error: parse HTTP status, map to the table above, tell the user exactly what to do. Duplicate tweet: if user tries to post the same text twice, tell them X blocks duplicate content and ask them to change the wording.

Category context

Code helpers, APIs, CLIs, browser automation, testing, and developer operations.

Source: Tencent SkillHub

Largest current source with strong distribution and engagement signals.

Package contents

Included in package
1 Docs1 Config
  • SKILL.md Primary doc
  • _meta.json Config