Add README and MIT license
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Matt Jackson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
204
README.md
Normal file
204
README.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# 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 <prompt-name>
|
||||
```
|
||||
|
||||
Schedule posts for the day (picks random times, waits, then posts):
|
||||
|
||||
```bash
|
||||
node scheduler.js <prompt-name>
|
||||
```
|
||||
|
||||
### 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. `<key>` 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 `<placeholder>` 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 <link> on its own line.",
|
||||
"links": {
|
||||
"link": "https://example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Multiple placeholders work too:
|
||||
|
||||
```json
|
||||
{
|
||||
"prompt": "Mention <site> and end with <cta>.",
|
||||
"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
|
||||
Reference in New Issue
Block a user