Skill: phy041/twitter-auto-engage (version 1.0.2)

--- name: twitter-auto-engage description: Automated Twitter/X engagement script that scans a curated pool of target accounts, generates authentic GPT-powered replies, and posts them via the Twitter GraphQL API. Use when you want to run a scheduled engagement routine that builds presence through high-quality, non-sycophantic replies to thought leaders in your niche. homepage: https://canlah.ai metadata: {"requires": ["python3", "openai", "rnet_twitter"], "env": ["OPENAI_API_KEY", "TWITTER_COOKIE_PATH"], "tags": ["twitter", "social-media", "engagement", "automation", "openai", "gpt"]} --- # Twitter Auto-Engage Automated Twitter/X engagement system that scans a pool of target accounts, selects their highest-engagement recent tweets, generates context-aware replies using GPT, and posts them with human-like timing. Built for founders and builders who want to grow through genuine technical conversation, not follower-baiting. ## Requirements ```bash pip install openai # rnet_twitter — async Twitter GraphQL client (see rnet_twitter.py) ``` You also need: - A valid Twitter/X session cookie file (`twitter_cookies.json`) - An OpenAI API key ## Setup ```bash export OPENAI_API_KEY="your_openai_api_key" export TWITTER_COOKIE_PATH="/path/to/twitter_cookies.json" ``` The script reads cookies from a JSON file exported from a logged-in browser session. See [Obtaining Twitter Cookies](#obtaining-twitter-cookies) below. ## Usage ```bash # Run a single engagement session (5 replies max) python auto_engage.py # Schedule 4x daily via cron (recommended) # Morning, midday, afternoon, evening sessions 0 8,12,16,21 * * * cd {skillDir} && python auto_engage.py >> logs/engage.log 2>&1 ``` ## Configuration Edit the following constants at the top of the script to customize behavior: | Constant | Default | Description | |----------|---------|-------------| | `TARGETS_PER_RUN` | 20 | Accounts to check each session | | `MAX_REPLIES_PER_RUN` | 5 | Maximum replies to post per session | | `RUN_PROBABILITY` | 0.85 | Randomized skip chance (human variability) | | `MIN_REPLY_LENGTH` | 80 | Minimum character count for a reply | | `MAX_REPLY_LENGTH` | 260 | Maximum character count for a reply | ## Target Account Pool Organize accounts into named categories with per-session quotas. The script randomly samples `TARGETS_PER_RUN` accounts from the full pool each session. Example structure: ```python TARGET_POOL = { "ai_builders": [ "simonw", # Example: ML tools, Datasette "swyx", # Example: AI engineering ], "indie_builders": [ "dvassallo", # Example: indie hacker "tdinh_me", # Example: bootstrapped SaaS ], "marketing": [ "harrydry", # Example: Marketing Examples "wes_kao", # Example: content strategy ], } CATEGORY_QUOTAS = { "ai_builders": 2, # replies per session "indie_builders": 2, "marketing": 1, } ``` Replace handles with accounts relevant to your niche and goals. ## Reply Generation Replies are generated by GPT using a structured voice prompt. The system enforces: ### Voice Rules (Configurable) - Direct, clear sentences — no filler words - Specific over vague: numbers, tool names, concrete observations - Intellectually curious tone — genuine questions, not rhetorical - Comfortable acknowledging uncertainty or failure ### Hard Bans (Built-in Filters) The generated reply is rejected and skipped if it contains: - Sycophantic openers: "Great post", "Love this", "So true", "Spot on", etc. - Casual slang: lol, damn, wild, ngl, fr, bro, lowkey, fire, bussin, no cap - Emojis (any Unicode > U+1F600) - Exclamation marks (configurable tolerance) - Corporate speak: leverage, synergy, paradigm, game-changer - Self-promotion or product name-dropping ### Three Reply Archetypes GPT is prompted to pick ONE of: **A) Micro-insight + Question** Share a specific observation from your own experience, then ask something you genuinely want answered. > "Ran into this building our brand tool — embeddings drift ~15% after 3 months without retraining. How often are you recalibrating?" **B) Respectful Challenge** Politely push back with data or a counterexample, then invite their perspective. > "Counterpoint: Stripe's docs are famously good but they still need a sales team for enterprise. Isn't the real question where self-serve stops working?" **C) Pattern Recognition** Connect their point to something non-obvious from a different domain. > "This mirrors what happened in recommendation systems — Netflix found that optimizing for clicks killed retention. The proxy metric trap is everywhere. What's your equivalent of 'watch time'?" ## Customizing Your Voice Edit the `USER_CONTEXT` variable (or equivalent prompt section) to describe your background: ```python USER_CONTEXT = """You are writing a Twitter reply as YOUR_NAME. BACKGROUND: - Brief description of who you are - What you're building - Genuine interests relevant to the accounts you target VOICE: - [Your preferred communication style] - [Specific things to include or avoid] """ ``` The more specific and authentic your context, the better the replies. ## State Management The script maintains `auto_reply_state.json` to track replied tweet IDs, preventing duplicate replies across sessions: ```json { "replied_tweets": ["tweet_id_1", "tweet_id_2"], "last_updated": "2026-03-06T09:30:00" } ``` State is capped at the last 100 tweet IDs to prevent unbounded growth. ## Engagement Logic For each selected account the script: 1. Fetches the 10 most recent original tweets (excluding retweets and @-replies) 2. Filters out tweet IDs already replied to 3. Selects the tweet with highest combined engagement (likes + replies) 4. Generates a reply via GPT — if GPT outputs `SKIP`, the tweet is marked seen and skipped 5. Likes the tweet first (pre-reply like is an algorithmic signal) 6. Posts the reply 7. Waits 3-6 seconds (randomized human-like delay) before moving to the next account ## Output Each session prints a summary and appends to your log. When called by a bot framework, the script outputs a JSON block after the `---JSON_OUTPUT---` separator for programmatic consumption: ```json [ { "target": "simonw", "tweet": "LLMs are increasingly being used for...", "reply": "The retrieval side of this is underrated...", "url": "https://x.com/simonw/status/...", "liked": true } ] ``` ## Obtaining Twitter Cookies 1. Log in to Twitter/X in Chrome or Firefox 2. Open DevTools > Application > Cookies > `https://x.com` 3. Export the cookie values to a JSON file in the format expected by `rnet_twitter.py` 4. Store the file at the path referenced by `TWITTER_COOKIE_PATH` Do not commit cookie files to version control. ## Rate Limiting Guidelines - 5 replies per session, 4 sessions per day = 20 replies/day maximum - 85% probability of running each session adds natural variability - 3-6 second delay between each reply action - 1-2 second delay between like and reply on the same tweet Twitter's informal limits for reply actions are not publicly documented, but staying under 50 replies/day and spacing them across multiple sessions avoids most friction. ## Troubleshooting **Reply not posting**: Verify your cookie file is fresh. Twitter sessions expire — re-export cookies from your browser. **GPT always outputs SKIP**: Your `USER_CONTEXT` may not align with the selected accounts. Ensure your background gives GPT enough to work with for the topic domain. **Too many sycophancy rejections**: GPT may default to affirmative openers. Increase the system prompt emphasis on the ban list or lower the temperature slightly. **Account flagged / rate limited by Twitter**: Reduce `MAX_REPLIES_PER_RUN` to 3 and `RUN_PROBABILITY` to 0.6 for a more conservative cadence. --- ## Author **[Canlah AI](https://canlah.ai)** — Run performance marketing without breaking your brand. - GitHub: [github.com/PHY041](https://github.com/PHY041) - All Skills: [clawhub.ai/PHY041](https://clawhub.ai/PHY041)


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (MEDIUM)