BioClaw x-integration
X (Twitter) integration for BioClaw. Post tweets, like, reply, retweet, and quote. Use for setup, testing, or troubleshooting X functionality. Triggers on "setup x", "x integration", "twitter", "post tweet", "tweet".
git clone https://github.com/Runchuan-BU/BioClaw
T=$(mktemp -d) && git clone --depth=1 https://github.com/Runchuan-BU/BioClaw "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/x-integration" ~/.claude/skills/runchuan-bu-bioclaw-x-integration && rm -rf "$T"
.claude/skills/x-integration/SKILL.mdX (Twitter) Integration
Browser automation for X interactions via WhatsApp.
Compatibility: BioClaw v1.0.0. Directory structure may change in future versions.
Features
| Action | Tool | Description |
|---|---|---|
| Post | | Publish new tweets |
| Like | | Like any tweet |
| Reply | | Reply to tweets |
| Retweet | | Retweet without comment |
| Quote | | Quote tweet with comment |
Prerequisites
Before using this skill, ensure:
- BioClaw is installed and running - WhatsApp connected, service active
- Dependencies installed:
npm ls playwright dotenv-cli || npm install playwright dotenv-cli - CHROME_PATH configured in
(if Chrome is not at default location):.env# Find your Chrome path mdfind "kMDItemCFBundleIdentifier == 'com.google.Chrome'" 2>/dev/null | head -1 # Add to .env CHROME_PATH=/path/to/Google Chrome.app/Contents/MacOS/Google Chrome
Quick Start
# 1. Setup authentication (interactive) npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts # Verify: data/x-auth.json should exist after successful login # 2. Rebuild container to include skill ./container/build.sh # Verify: Output shows "COPY .claude/skills/x-integration/agent.ts" # 3. Rebuild host and restart service npm run build launchctl kickstart -k gui/$(id -u)/com.bioclaw # Verify: launchctl list | grep bioclaw shows PID and exit code 0
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
| | Chrome executable path |
| | Project root directory |
| | Logging level (debug, info, warn, error) |
Set in
.env file (loaded via dotenv-cli at runtime):
# .env CHROME_PATH=/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
Configuration File
Edit
lib/config.ts to modify defaults:
export const config = { // Browser viewport viewport: { width: 1280, height: 800 }, // Timeouts (milliseconds) timeouts: { navigation: 30000, // Page navigation elementWait: 5000, // Wait for element afterClick: 1000, // Delay after click afterFill: 1000, // Delay after form fill afterSubmit: 3000, // Delay after submit pageLoad: 3000, // Initial page load }, // Tweet limits limits: { tweetMaxLength: 280, }, };
Data Directories
Paths relative to project root:
| Path | Purpose | Git |
|---|---|---|
| Chrome profile with X session | Ignored |
| Auth state marker | Ignored |
| Service logs (contains X operation logs) | Ignored |
Architecture
┌─────────────────────────────────────────────────────────────┐ │ Container (Linux VM) │ │ └── agent.ts → MCP tool definitions (x_post, etc.) │ │ └── Writes IPC request to /workspace/ipc/tasks/ │ └──────────────────────┬──────────────────────────────────────┘ │ IPC (file system) ▼ ┌─────────────────────────────────────────────────────────────┐ │ Host (macOS) │ │ └── src/ipc.ts → processTaskIpc() │ │ └── host.ts → handleXIpc() │ │ └── spawn subprocess → scripts/*.ts │ │ └── Playwright → Chrome → X Website │ └─────────────────────────────────────────────────────────────┘
Why This Design?
- API is expensive - X official API requires paid subscription ($100+/month) for posting
- Bot browsers get blocked - X detects and bans headless browsers and common automation fingerprints
- Must use user's real browser - Reuses the user's actual Chrome on Host with real browser fingerprint to avoid detection
- One-time authorization - User logs in manually once, session persists in Chrome profile for future use
File Structure
.claude/skills/x-integration/ ├── SKILL.md # This documentation ├── host.ts # Host-side IPC handler ├── agent.ts # Container-side MCP tool definitions ├── lib/ │ ├── config.ts # Centralized configuration │ └── browser.ts # Playwright utilities └── scripts/ ├── setup.ts # Interactive login ├── post.ts # Post tweet ├── like.ts # Like tweet ├── reply.ts # Reply to tweet ├── retweet.ts # Retweet └── quote.ts # Quote tweet
Integration Points
To integrate this skill into BioClaw, make the following modifications:
1. Host side: src/ipc.ts
Add import after other local imports:
import { handleXIpc } from '../.claude/skills/x-integration/host.js';
Modify
processTaskIpc function's switch statement default case:
// Find: default: logger.warn({ type: data.type }, 'Unknown IPC task type'); // Replace with: default: const handled = await handleXIpc(data, sourceGroup, isMain, DATA_DIR); if (!handled) { logger.warn({ type: data.type }, 'Unknown IPC task type'); }
2. Container side: container/agent-runner/src/ipc-mcp.ts
Add import after
cron-parser import:
// @ts-ignore - Copied during Docker build from .claude/skills/x-integration/ import { createXTools } from './skills/x-integration/agent.js';
Add to the end of tools array (before the closing
]):
...createXTools({ groupFolder, isMain })
3. Build script: container/build.sh
Change build context from
container/ to project root (required to access .claude/skills/):
# Find: container build -t "${IMAGE_NAME}:${TAG}" . # Replace with: cd "$SCRIPT_DIR/.." container build -t "${IMAGE_NAME}:${TAG}" -f container/Dockerfile .
4. Dockerfile: container/Dockerfile
First, update the build context paths (required to access
.claude/skills/ from project root):
# Find: COPY agent-runner/package*.json ./ ... COPY agent-runner/ ./ # Replace with: COPY container/agent-runner/package*.json ./ ... COPY container/agent-runner/ ./
Then add COPY line after
COPY container/agent-runner/ ./ and before RUN npm run build:
# Copy skill MCP tools COPY .claude/skills/x-integration/agent.ts ./src/skills/x-integration/
Setup
All paths below are relative to project root (
BIOCLAW_ROOT).
1. Check Chrome Path
# Check if Chrome exists at configured path cat .env | grep CHROME_PATH ls -la "$(grep CHROME_PATH .env | cut -d= -f2)" 2>/dev/null || \ echo "Chrome not found - update CHROME_PATH in .env"
2. Run Authentication
npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts
This opens Chrome for manual X login. Session saved to
data/x-browser-profile/.
Verify success:
cat data/x-auth.json # Should show {"authenticated": true, ...}
3. Rebuild Container
./container/build.sh
Verify success:
./container/build.sh 2>&1 | grep -i "agent.ts" # Should show COPY line
4. Restart Service
npm run build launchctl kickstart -k gui/$(id -u)/com.bioclaw
Verify success:
launchctl list | grep bioclaw # Should show PID and exit code 0 or -
Usage via WhatsApp
Replace
@Assistant with your configured trigger name (ASSISTANT_NAME in .env):
@Assistant post a tweet: Hello world! @Assistant like this tweet https://x.com/user/status/123 @Assistant reply to https://x.com/user/status/123 with: Great post! @Assistant retweet https://x.com/user/status/123 @Assistant quote https://x.com/user/status/123 with comment: Interesting
Note: Only the main group can use X tools. Other groups will receive an error.
Testing
Scripts require environment variables from
.env. Use dotenv-cli to load them:
Check Authentication Status
# Check if auth file exists and is valid cat data/x-auth.json 2>/dev/null && echo "Auth configured" || echo "Auth not configured" # Check if browser profile exists ls -la data/x-browser-profile/ 2>/dev/null | head -5
Re-authenticate (if expired)
npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts
Test Post (will actually post)
echo '{"content":"Test tweet - please ignore"}' | npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/post.ts
Test Like
echo '{"tweetUrl":"https://x.com/user/status/123"}' | npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/like.ts
Or export
CHROME_PATH manually before running:
export CHROME_PATH="/path/to/chrome" echo '{"content":"Test"}' | npx tsx .claude/skills/x-integration/scripts/post.ts
Troubleshooting
Authentication Expired
npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts launchctl kickstart -k gui/$(id -u)/com.bioclaw
Browser Lock Files
If Chrome fails to launch:
rm -f data/x-browser-profile/SingletonLock rm -f data/x-browser-profile/SingletonSocket rm -f data/x-browser-profile/SingletonCookie
Check Logs
# Host logs (relative to project root) grep -i "x_post\|x_like\|x_reply\|handleXIpc" logs/bioclaw.log | tail -20 # Script errors grep -i "error\|failed" logs/bioclaw.log | tail -20
Script Timeout
Default timeout is 2 minutes (120s). Increase in
host.ts:
const timer = setTimeout(() => { proc.kill('SIGTERM'); resolve({ success: false, message: 'Script timed out (120s)' }); }, 120000); // ← Increase this value
X UI Selector Changes
If X updates their UI, selectors in scripts may break. Current selectors:
| Element | Selector |
|---|---|
| Tweet input | |
| Post button | |
| Reply button | |
| Like | |
| Unlike | |
| Retweet | |
| Unretweet | |
| Confirm retweet | |
| Modal dialog | |
| Modal submit | |
Container Build Issues
If MCP tools not found in container:
# Verify build copies skill ./container/build.sh 2>&1 | grep -i skill # Check container has the file container run bioclaw-agent ls -la /app/src/skills/
Security
- Contains X session cookies (indata/x-browser-profile/
).gitignore
- Auth state marker (indata/x-auth.json
).gitignore- Only main group can use X tools (enforced in
andagent.ts
)host.ts - Scripts run as subprocesses with limited environment