AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Twitter

skill-hankunpeng-skills-twitter · by hankunpeng

Posts content, deletes tweets, or exports/saves tweets to YAML on X (Twitter) using Chrome Computer Use Mode. Use when user requests "post to Twitter", "tweet", "share on X", "post to X", "delete tweet", "export tweets", or "save tweets".

No reviews yet
0 installs
10 views
0.0% view→install

Install

$ agentstack add skill-hankunpeng-skills-twitter

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-hankunpeng-skills-twitter)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Twitter? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Twitter Skill

Posts text and images to X (Twitter) via Chrome Computer Use Mode.

Script Directory

Important: All scripts are located in the scripts/ subdirectory of this skill.

Agent Execution Instructions:

  1. Determine this SKILL.md file's directory path as {baseDir}
  2. Script paths:
  • Setup / Initializer: {baseDir}/scripts/setup.ts
  • Clipboard helper: {baseDir}/scripts/copy-to-clipboard.ts
  • Tweet exporter/scraper: {baseDir}/scripts/export-tweets.ts
  • Official X API helper: {baseDir}/scripts/x-api.ts
  1. Resolve ${BUN_X} runtime: if bun installed → bun; if npx available → npx -y bun; else suggest installing bun
  2. Replace all {baseDir} and ${BUN_X} in this document with actual values
  3. Initial Setup: Run the setup script to automatically initialize configuration folders and template files:

``bash ${BUN_X} {baseDir}/scripts/setup.ts ``

Execution Mode

This skill follows a Hybrid Execution Model:

  1. API First (Recommended for text posts): Attempt to post the tweet using the official X API script (x-api.ts). This is fast, stable, and uses no browser resources.
  2. Browser Fallback: If the API call fails (e.g., monthly 1500-tweet Free tier quota exceeded, rate limit) or API credentials are not configured in ~/.config/skills/twitter.yaml, fall back automatically to Chrome Computer Use Mode / CLI Bridge to simulate browser actions.

Prerequisites

  • For API Mode: Configure your X API credentials and state in your global ~/.config/skills/twitter.yaml file:

```yaml xapi: apikey: "YOURAPIKEY" apikeysecret: "YOURAPIKEYSECRET" accesstoken: "YOURACCESSTOKEN" accesstokensecret: "YOURACCESSTOKEN_SECRET"

state: useapi: true lastreset_month: "2026-06" ```

#### X Developer Portal Setup Guide:

  1. Go to the X Developer Portal.
  2. Select your App under Projects & Apps.
  3. Under User authentication settings, click Set up (or Edit):
  • App permissions: Select Read and write.
  • Type of App: Select Web App, Automated App or Bot.
  • Callback URI / Redirect URL: Enter https://127.0.0.1 (required placeholder).
  • Website URL: Enter your project URL, e.g. https://github.com/hankunpeng/skills (required placeholder).
  • Save the settings.
  1. Go to the Keys and Tokens tab:
  • Under Consumer Keys, copy or regenerate the API Key and API Key Secret.
  • Under Access Token and Secret, click Regenerate to obtain the Access Token and Access Token Secret (Note: tokens must be regenerated after changing permissions to activate write access).
  1. Copy these 4 credentials and paste them into ~/.config/skills/twitter.yaml.
  • For Browser Fallback: Google Chrome installed, logged into X (Twitter) in Chrome, and macOS accessibility permissions granted if required.

Regular Posts Workflow (Text & Images)

When executing a post:

  1. Start the agent turn by calling get_app_state (or equivalent tool) for Google Chrome.
  2. Open or navigate Google Chrome to https://x.com/compose/post.
  3. Locate the tweet composer input box.
  4. Type the post text into the composer using Computer Use keyboard inputs.
  5. If there are any images to attach (max 4):

For each image: a. Run the clipboard helper script to copy the image to the clipboard: ``bash ${BUN_X} {baseDir}/scripts/copy-to-clipboard.ts image /absolute/path/to/image.png ` b. Paste the image into the composer using the paste shortcut (super+v on macOS, control+v` on Windows/Linux). c. Wait 2-3 seconds until X finishes uploading the media.

  1. Publish Safety: Never click Publish, Post, or any equivalent button to publish the tweet without getting explicit final confirmation from the user in the current conversation.
  2. Once the user confirms, click the Post button to publish.
  3. After publishing, close the composer modal so the UI doesn't stay stuck on the compose dialog. Use the close button or Escape:
  • DOM Selector: [data-testid="app-bar-close"] or [aria-label="Close"]
  • Fallback: dispatch an Escape keydown event
  1. Auto-Reload Feed (Optional): If the user has other tabs open to their profile (e.g., x.com/[username]) or home feed (x.com/home), reload them so the new tweet is visible immediately.
var closeBtn = document.querySelector('[data-testid="app-bar-close"], [aria-label="Close"]');
if (closeBtn) { closeBtn.click(); }
else { document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', code: 'Escape', keyCode: 27, which: 27, bubbles: true })); }

CLI Bridge (No Computer Use Tools)

When the environment lacks Computer Use keyboard/mouse tools, use platform-specific methods to open Chrome and inject JavaScript into the page.

macOS (AppleScript)

Open compose page:

open -a "Google Chrome" "https://x.com/compose/post"

Execute JavaScript in Chrome — write JS to a temp file first (avoids shell escaping issues), then run via AppleScript:

cat > /tmp/tweet.js  1 ? els[els.length - 1] : els[0];
   ```
   Always target the active modal composer (usually the last element in the list).

2. **Binding Selection & Focus**:
   Before inserting text, you MUST click the element to trigger Draft.js selection binding, then focus:
   ```javascript
   el.click();
   el.focus();
   ```

3. **Preserving Editor Structure**:
   - **Do NOT** use `el.innerHTML = ''` or `document.execCommand('delete')` on an empty composer. Wiping the DOM nodes destroys Draft.js's internal wrapper structure (e.g., `public-DraftStyleDefault-block` span), which crashes the React component and leaves the Post button permanently disabled.
   - Simply use `document.execCommand('insertText', false, text)` directly into the empty focused editor.

4. **Triggering React State Updates**:
   After text insertion, dispatch a bubbled `input` event to notify React:
   ```javascript
   el.dispatchEvent(new Event('input', { bubbles: true }));
   ```

5. **Locating the Correct Post Button**:
   The button testids (`tweetButtonInline` and `tweetButton`) might be swapped depending on the context. Always scan for the visible, enabled button:
   ```javascript
   var btns = document.querySelectorAll('[data-testid="tweetButtonInline"], [data-testid="tweetButton"]');
   var activeBtn = Array.from(btns).find(function(btn) {
       var isVisible = btn.offsetWidth > 0 && btn.offsetHeight > 0;
       var isDisabled = btn.disabled || btn.getAttribute('aria-disabled') === 'true';
       return isVisible && !isDisabled;
   });
    if (activeBtn) activeBtn.click();
    ```

## Delete Tweet Workflow

When executing a deletion:

1. Open or navigate Google Chrome to the user's profile page (`https://x.com/[username]`) or the direct tweet URL (`https://x.com/[username]/status/[tweetId]`).
2. Search for the target tweet `` container containing the text to delete.
3. Click the options menu button on the tweet:
   - **DOM Selector**: `[data-testid="caret"]`
4. Wait 1-2 seconds, then click the "Delete" menu item:
   - **DOM Selector**: A `[role="menuitem"]` element whose text contains "Delete" or "删除".
5. Wait 1-2 seconds, then click the confirmation delete button in the dialog sheet:
   - **DOM Selector**: `[data-testid="confirmationSheetConfirm"]` (or fallback to any dialog button with text "Delete" or "删除").

### CLI Bridge Example (macOS)

Use the same temp-file + AppleScript pattern as posting. Replace `TWEET_TEXT_HERE` with the target tweet content.

**Step 1 — Find tweet and click caret:**

```bash
cat > /tmp/del-1.js  /tmp/del-2.js  /tmp/del-3.js << 'EOF'
(function() {
  var confirmBtn = document.querySelector('[data-testid="confirmationSheetConfirm"]');
  if (!confirmBtn) {
    var buttons = document.querySelectorAll('[role="button"], button');
    for (var i = 0; i < buttons.length; i++) {
      var txt = buttons[i].textContent.trim();
      if (txt === 'Delete' || txt === '删除') {
        confirmBtn = buttons[i];
        break;
      }
    }
  }
  if (!confirmBtn) return 'ERROR: confirm button not found';
  confirmBtn.click();
  return 'OK: confirm clicked';
})();
EOF

osascript -e '
tell application "Google Chrome"
    set js to read "/tmp/del-3.js"
    set result to execute front window'"'"'s active tab javascript js
    return result
end tell'

Export Tweets Workflow

To export/save all or filtered tweets from your profile page:

  1. Run the exporter script:

``bash ${BUN_X} {baseDir}/scripts/export-tweets.ts [startDate] [endDate] ``

  • Optional Date Filters: You can pass startDate (e.g. 2026-06-01) and endDate (e.g. 2026-06-30) to filter the output by date range. If omitted, all scraped tweets are exported.
  • Output File: The tweets will be saved in /Users/alex/twitter/twitter.yaml where the tweet URL is the key, and the tweet text content is the value.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.