# xBot AI-powered Twitter/X bot that generates and posts tweets on configurable schedules using stealth browser automation. ## How it works 1. **Scheduler** runs via cron, picks random times within a configured window 2. **Bot** logs into X via [Kernel.sh](https://onkernel.com) stealth browsers (residential proxies + CAPTCHA solving) 3. **Claude** (Anthropic API) generates tweets based on your prompts 4. **Links** are inserted after generation — URLs never touch the AI 5. **History** is tracked per-prompt and fed back to avoid repetition ## Setup ### Prerequisites - Node.js 18+ - [Kernel.sh](https://onkernel.com) API key - [Anthropic](https://console.anthropic.com) API key - An X/Twitter account ### Install ```bash git clone https://github.com/MattJackson/xBot.git cd xBot npm install ``` ### Configure 1. Copy the example files: ```bash cp .env.example .env cp prompts.example.json prompts.json ``` 2. Edit `.env` with your credentials: ``` MYACCOUNT_USER=your_twitter_handle MYACCOUNT_PW=your_password MYACCOUNT_EMAIL=your_email@example.com MYACCOUNT_PHONE=1234567890 KERNEL=sk_your_kernel_key ANTHROPIC=sk-ant-your_anthropic_key ``` Credentials are prefixed by account name (uppercase). To add another account, add another set: ``` ANOTHERACCOUNT_USER=... ANOTHERACCOUNT_PW=... ANOTHERACCOUNT_EMAIL=... ANOTHERACCOUNT_PHONE=... ``` 3. Edit `prompts.json` with your prompts (see [Prompt Configuration](#prompt-configuration) below). ### Run Post a single tweet: ```bash node bot.js ``` Schedule posts for the day (picks random times, waits, then posts): ```bash node scheduler.js ``` ### Cron Add a cron job for each prompt. The scheduler handles random timing within the window — cron just needs to trigger it once daily before the window opens. ```bash crontab -e ``` ``` # Runs daily — scheduler picks random time(s) between 8am-8pm PST 0 16 * * * cd /path/to/xBot && /usr/bin/node scheduler.js my-prompt >> bot.log 2>&1 ``` The cron time should be in UTC. `0 16 * * *` = midnight PST (8 hours ahead), ensuring the scheduler starts before the 8am PST window. ## Prompt Configuration `prompts.json` is an array of prompt objects: ```json [ { "name": "my-prompt", "account": "myaccount", "prompt": "Your prompt text here. Generate 1 tweet. Just the tweet.", "links": { "link": "https://example.com" }, "schedule": { "type": "daily", "window": [8, 20], "postsPerDay": [1, 3], "minGapHours": 4 } } ] ``` ### Fields | Field | Required | Description | |-------|----------|-------------| | `name` | Yes | Unique identifier. Used as CLI argument and for history files. | | `account` | Yes | Maps to env var prefix. `"myaccount"` looks up `MYACCOUNT_USER`, etc. | | `prompt` | Yes | The prompt sent to Claude. Include generation instructions here. | | `links` | No | Key-value map. `` placeholders in the generated tweet are replaced with the URL. URLs never reach the AI. | | `schedule` | Yes | Scheduling configuration (see below). | ### Schedule types **Daily** — posts every day, 1 or more times: ```json { "type": "daily", "window": [8, 20], "postsPerDay": [1, 3], "minGapHours": 4 } ``` - `window`: `[startHour, endHour]` in PST. Posts only happen within this range. - `postsPerDay`: `[min, max]`. A random count is picked each day. Defaults to `[1, 1]`. - `minGapHours`: Minimum hours between posts on the same day. Defaults to `4`. **Random** — posts on random days with a minimum gap: ```json { "type": "random", "window": [8, 20], "minDays": 2 } ``` - `minDays`: Minimum days between posts. After the gap is met, there's a 50% chance each day — so actual spacing varies naturally (2, 3, 4+ days). ### Link placeholders Use `` in your prompt instructions. The AI generates the tweet with the placeholder, then the bot replaces it with the real URL: ```json { "prompt": "Write a tweet. End with on its own line.", "links": { "link": "https://example.com" } } ``` Multiple placeholders work too: ```json { "prompt": "Mention and end with .", "links": { "site": "https://mysite.com", "cta": "https://mysite.com/signup" } } ``` ## Multi-account Each prompt specifies which account to post from. You can run multiple accounts from the same instance: ```json [ { "name": "account1-daily", "account": "firstaccount", "prompt": "...", "schedule": { ... } }, { "name": "account2-promo", "account": "secondaccount", "prompt": "...", "schedule": { ... } } ] ``` Just add the corresponding credentials to `.env` for each account. ## Files | File | Tracked | Description | |------|---------|-------------| | `bot.js` | Yes | Main bot — login, generate, post | | `scheduler.js` | Yes | Picks random times, runs bot.js | | `prompts.json` | No | Your prompt config (create from example) | | `.env` | No | Your credentials | | `history-*.json` | No | Per-prompt tweet history | | `bot.log` | No | Cron output log | ## License MIT