diff --git a/.env.example b/.env.example index 84d77d88..9792c34f 100644 --- a/.env.example +++ b/.env.example @@ -1,144 +1,32 @@ -# XActions Configuration -# Copy this file to .env and fill in your values +# XActions Environment Variables +# Copy this to .env and fill in your values +# NEVER commit .env to git -# ═══════════════════════════════════════════════════════════════════════════════ -# Server Configuration -# ═══════════════════════════════════════════════════════════════════════════════ +# X/Twitter Session Cookie +# Get this from: DevTools (F12) -> Application -> Cookies -> x.com -> auth_token +XACTIONS_SESSION_COOKIE=your_auth_token_here -NODE_ENV=development -PORT=3001 -API_URL=http://localhost:3001 -API_BASE_URL=http://localhost:3001 -FRONTEND_URL=http://localhost:3000 - -# ═══════════════════════════════════════════════════════════════════════════════ -# x402 Payment Configuration (AI Agent Monetization) -# ═══════════════════════════════════════════════════════════════════════════════ - -# ⚠️ REQUIRED for production - your wallet address to receive USDC payments -# This MUST be set to a valid Ethereum address (0x...) for x402 to work -# Server will fail to start in production if this is not configured -X402_PAY_TO_ADDRESS=0x4027FdaC1a5216e264A00a5928b8366aE59cE888 - -# Network: which blockchain to use for payments -# eip155:8453 = Base mainnet (REAL money - use for production) -# eip155:84532 = Base Sepolia testnet (TEST money - use for development) -# Defaults: testnet in development, mainnet in production -X402_NETWORK=eip155:84532 - -# Facilitator URL for payment verification and settlement -# Default works for most cases, only change if using custom facilitator -X402_FACILITATOR_URL=https://x402.org/facilitator - -# Debug logging for x402 payments (optional) -X402_DEBUG=false - -# Skip payment verification in development (NEVER use in production!) -# Uncomment ONLY for local testing without a wallet -# X402_SKIP_VERIFICATION=true - -# ═══════════════════════════════════════════════════════════════════════════════ -# Payment Webhook Notifications (Optional - for revenue tracking) -# ═══════════════════════════════════════════════════════════════════════════════ - -# Custom webhook URL - receives JSON POST for all payment events -# This is the recommended option - just point to your own endpoint -# Payload: { event, timestamp, data: { amount, operation, payer, network, txHash } } -X402_WEBHOOK_URL=https://your-server.com/webhooks/payments - -# Webhook signature secret (optional but recommended for production) -# Signs payloads with HMAC-SHA256 for security -# Verify: X-Webhook-Signature header = HMAC-SHA256(timestamp.payload, secret) -# Generate with: openssl rand -hex 32 -X402_WEBHOOK_SECRET= - -# Optional: Discord/Slack webhooks (leave empty if not using) -# DISCORD_WEBHOOK_URL= -# SLACK_WEBHOOK_URL= - -# ═══════════════════════════════════════════════════════════════════════════════ -# Stripe Billing (Subscription Payments) -# ═══════════════════════════════════════════════════════════════════════════════ - -# Get your keys from https://dashboard.stripe.com/apikeys -STRIPE_SECRET_KEY=sk_test_... -STRIPE_PUBLISHABLE_KEY=pk_test_... - -# Webhook signing secret — from Stripe Dashboard > Webhooks > Signing secret -# Endpoint URL: https://your-domain.com/webhooks/stripe -STRIPE_WEBHOOK_SECRET=whsec_... - -# Price IDs — create these in Stripe Dashboard > Products -# Each should be a recurring monthly price -STRIPE_PRO_PRICE_ID=price_... -STRIPE_BUSINESS_PRICE_ID=price_... -STRIPE_ENTERPRISE_PRICE_ID=price_... - -# ═══════════════════════════════════════════════════════════════════════════════ -# MCP Server Configuration (for AI agents like Claude) -# ═══════════════════════════════════════════════════════════════════════════════ - -# MCP mode: local (free, uses Puppeteer) or remote (paid, uses x402 API) +# Mode: 'local' (default, uses Puppeteer) or 'remote' (cloud API) XACTIONS_MODE=local -# API URL for remote mode +# Remote mode settings (only needed if XACTIONS_MODE=remote) XACTIONS_API_URL=https://api.xactions.app -# Private key for x402 payments (remote mode only) -# ⚠️ NEVER commit this value! Use a separate wallet for payments. -# X402_PRIVATE_KEY=0xYourPrivateKey - -# X/Twitter session cookie for authentication -XACTIONS_SESSION_COOKIE= - -# ═══════════════════════════════════════════════════════════════════════════════ -# Database (PostgreSQL) -# ═══════════════════════════════════════════════════════════════════════════════ - -DATABASE_URL="postgresql://user:password@localhost:5432/xactions?schema=public" - -# ═══════════════════════════════════════════════════════════════════════════════ -# Authentication & Security -# ═══════════════════════════════════════════════════════════════════════════════ - -JWT_SECRET=your-super-secret-jwt-key-change-this-in-production -SESSION_SECRET=your-session-secret-key - -# Admin API key for accessing admin endpoints (payment stats, webhook management) -# Generate a secure random string: openssl rand -hex 32 -ADMIN_API_KEY= +# Optional: x420 micropayments (remote mode) +X402_PRIVATE_KEY= +X402_NETWORK=base-sepolia -# CORS allowed origins (comma-separated) -CORS_ORIGINS=http://localhost:3000,http://localhost:3001,https://xactions.app +# Optional: AI-generated content via XActions +OPENROUTER_API_KEY= -# ═══════════════════════════════════════════════════════════════════════════════ -# Twitter/X OAuth 2.0 -# ═══════════════════════════════════════════════════════════════════════════════ +# Database (Docker Compose defaults) +POSTGRES_PASSWORD=xactions_dev_password +DATABASE_URL=postgresql://xactions:xactions_dev_password@localhost:5432/xactions?schema=public -TWITTER_CLIENT_ID=your_twitter_client_id -TWITTER_CLIENT_SECRET=your_twitter_client_secret -TWITTER_BEARER_TOKEN=your_twitter_bearer_token - -# ═══════════════════════════════════════════════════════════════════════════════ -# Redis (for job queue) -# ═══════════════════════════════════════════════════════════════════════════════ - -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD= - -# ═══════════════════════════════════════════════════════════════════════════════ -# Puppeteer Configuration (for local mode) -# ═══════════════════════════════════════════════════════════════════════════════ - -PUPPETEER_HEADLESS=true -PUPPETEER_NO_SANDBOX=true -# PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser - -# ═══════════════════════════════════════════════════════════════════════════════ -# Logging & Monitoring -# ═══════════════════════════════════════════════════════════════════════════════ - -LOG_LEVEL=info -# SENTRY_DSN=https://xxx@sentry.io/xxx +# API Server +PORT=3001 +JWT_SECRET=change_this_to_a_random_string +SESSION_SECRET=change_this_too +# Hermes Integration +HERMES_CONTENT_DIR=~/.hermes/cron/output diff --git a/AGENTS.md b/AGENTS.md index b28ef773..d19946e6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,7 +34,9 @@ extension/ → Browser extension (Chrome/Edge) ## Skills -31 skills in `skills/*/SKILL.md`. Read the relevant SKILL.md when a user's request matches a category. +32 skills in `skills/*/SKILL.md`. Read the relevant SKILL.md when a user's request matches a category. + +- **Hermes integration** — `skills/hermes-integration/SKILL.md` — content pipeline from Hermes to X/Twitter - **Unfollow management** — mass unfollow, non-follower cleanup - **Analytics & insights** — engagement, hashtags, competitors, best times @@ -104,9 +106,35 @@ Common resource hogs: `tsgo --noEmit` (~500% CPU), vitest workers (15x ~100% CPU - Do not reuse foreground shell sessions — stale sessions block future operations - If a terminal appears unresponsive, kill it and create a new one +## Hermes Integration + +This repo is integrated with Hermes Agent for AI-powered content generation. + +### Content Pipeline + +1. Hermes generates security content (vulnerability threads, exploit analysis) +2. All content is deslopped (no AI patterns, em dashes, hedging) +3. Hermes sends content to the user via Telegram +4. **User posts manually** — no automation, no API keys needed + +### Key Files + +| File | Purpose | +|------|---------| +| `skills/hermes-integration/SKILL.md` | Full integration guide | +| `scripts/hermes-poster.js` | Format content for manual posting | +| `.env.example` | Environment variable template (for future automation) | + +### Environment + +- `.env` is in `.gitignore` — never commit secrets +- Content directory: `~/.hermes/cron/output/` + ## Mandatory Rules 1. **Never mock, stub, or fake anything.** Real implementations only. 2. **TypeScript strict mode** — no `any`, no `@ts-ignore`. 3. **Always kill terminals** after commands complete. -4. **Always commit and push** as `nirholas`. +4. **Always commit and push** as `preciousnwankwo`. +5. **Never commit `.env` files, session cookies, or API keys.** +6. **Never auto-post content. The user posts all content manually.** \ No newline at end of file diff --git a/config/hermes-mcp-config.json b/config/hermes-mcp-config.json new file mode 100644 index 00000000..e31c3986 --- /dev/null +++ b/config/hermes-mcp-config.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "xactions": { + "command": "npx", + "args": ["-y", "xactions-mcp"], + "env": { + "XACTIONS_SESSION_COOKIE": "${XACTIONS_SESSION_COOKIE}", + "XACTIONS_MODE": "local" + } + } + } +} diff --git a/docs/hermes-integration.md b/docs/hermes-integration.md new file mode 100644 index 00000000..1160d6f9 --- /dev/null +++ b/docs/hermes-integration.md @@ -0,0 +1,64 @@ +# Hermes Agent Integration + +XActions integrates with [Hermes Agent](https://hermes-agent.nousresearch.com/) for AI-powered Twitter content generation. + +## Overview + +1. **Hermes generates content** — security threads, vulnerability breakdowns, exploit analysis +2. **Deslop pass** — all output is stripped of AI patterns (no em dashes, hedging, AI vocabulary) +3. **User posts manually** — Hermes sends content to the user via Telegram. The user copies and posts it. + +No X API keys. No session cookies. No browser automation. Just content generation. + +## Quick Start + +### 1. Generate Content + +Hermes uses the security content pool at `~/.hermes/scripts/security-content-generator.py` to generate threads. Content is automatically deslopped. + +### 2. Receive Content + +Hermes sends content to the user via Telegram, 3 times daily: +- Morning (9:00 UTC) +- Afternoon (14:00 UTC) +- Evening (22:37 UTC) + +### 3. Post Manually + +The user copies the content and posts it to X/Twitter manually. No automation. + +## Content Pipeline + +``` +Security Content Pool (26+ threads, auto-refreshed weekly) + ↓ + Hermes picks topic (no repeats) + ↓ + Deslop transformation + ↓ + Hermes sends to user (Telegram) + ↓ + User copies and posts manually + ↓ + Log sent thread (no duplicates) +``` + +## Content Types + +- **Single tweet** — one vulnerability insight, under 280 chars +- **Thread** — 3-8 tweets breaking down an exploit, with hook + value + CTA + +## Safety + +- **No auto-posting** — the user posts all content manually +- **No duplicate content** — sent threads are logged and never repeated +- **No secrets in repo** — `.env` is in `.gitignore` +- **No X API keys needed** — no automation means no keys + +## Files + +| File | Purpose | +|------|---------| +| `skills/hermes-integration/SKILL.md` | Full integration guide | +| `scripts/hermes-poster.js` | Format content for manual posting | +| `.env.example` | Environment template (for future automation) | diff --git a/scripts/hermes-poster.js b/scripts/hermes-poster.js new file mode 100644 index 00000000..2f1843e4 --- /dev/null +++ b/scripts/hermes-poster.js @@ -0,0 +1,95 @@ +#!/usr/bin/env node +// Hermes Content Poster — Format deslopped content for manual posting +// Usage: node hermes-poster.js [content-file] +// Reads a content file, splits it into tweet-sized chunks, outputs copy-paste ready text + +import fs from 'node:fs'; +import path from 'node:path'; + +const CONTENT_DIR = process.env.HERMES_CONTENT_DIR || `${process.env.HOME}/.hermes/cron/output`; + +function parseContent(raw) { + const lines = raw.trim().split('\n'); + const title = lines[0].replace(/[:\-–—].*$/, '').trim(); + const body = lines.slice(1).join('\n').trim(); + const tweets = splitIntoTweets(body); + return { title, body, tweets }; +} + +function splitIntoTweets(text) { + const maxLen = 280; + const tweets = []; + const sentences = text.match(/[^.!?]+[.!?]+/g) || [text]; + + let current = ''; + for (const sentence of sentences) { + if ((current + ' ' + sentence).trim().length <= maxLen) { + current = (current + ' ' + sentence).trim(); + } else { + if (current) tweets.push(current); + if (sentence.length <= maxLen) { + current = sentence.trim(); + } else { + const words = sentence.split(' '); + current = ''; + for (const word of words) { + if ((current + ' ' + word).length <= maxLen) { + current = (current + ' ' + word).trim(); + } else { + if (current) tweets.push(current); + current = word; + } + } + } + } + } + if (current) tweets.push(current); + + if (tweets.length > 1) { + return tweets.map((t, i) => `${i + 1}/${tweets.length} ${t}`); + } + return tweets; +} + +function main() { + const inputFile = process.argv[2]; + if (!inputFile) { + const files = fs.readdirSync(CONTENT_DIR) + .filter(f => f.startsWith('security-thread_') && f.endsWith('.txt')) + .sort().reverse().slice(0, 10); + + if (files.length === 0) { + console.log('No content files found.'); + process.exit(1); + } + + console.log('Available content files:'); + files.forEach((f, i) => console.log(` ${i + 1}. ${f}`)); + console.log('\nUsage: node hermes-poster.js '); + process.exit(0); + } + + const filePath = path.isAbsolute(inputFile) ? inputFile : path.join(CONTENT_DIR, inputFile); + if (!fs.existsSync(filePath)) { + console.error(`File not found: ${filePath}`); + process.exit(1); + } + + const raw = fs.readFileSync(filePath, 'utf-8'); + const { title, tweets } = parseContent(raw); + + console.log(`\n${'='.repeat(60)}`); + console.log(`Title: ${title}`); + console.log(`Tweets: ${tweets.length}`); + console.log(`${'='.repeat(60)}\n`); + + tweets.forEach((t, i) => { + console.log(`--- Tweet ${i + 1} (${t.length} chars) ---`); + console.log(t); + console.log(); + }); + + console.log('Copy each tweet above and post to X/Twitter manually.'); +} + +main(); diff --git a/skills/hermes-integration/SKILL.md b/skills/hermes-integration/SKILL.md new file mode 100644 index 00000000..98d8a14a --- /dev/null +++ b/skills/hermes-integration/SKILL.md @@ -0,0 +1,71 @@ +--- +name: hermes-integration +description: Integrates XActions with Hermes Agent for AI-powered Twitter/X content generation. Hermes generates deslopped security content and sends it to the user for manual posting. No automation of posting — the user posts themselves. Use when the user wants to generate Twitter content through Hermes or manage the content pipeline from Hermes to X/Twitter. +license: MIT +metadata: + author: fisher + version: "1.1" +--- + +# Hermes Integration + +Bridge between Hermes Agent and XActions for Twitter/X content generation. + +## How It Works + +1. **Hermes generates content** — security threads, vulnerability breakdowns, exploit analysis +2. **Deslop pass** — all output is run through deslop (no em dashes, AI vocabulary, hedging) +3. **User posts manually** — Hermes sends the content to the user. The user copies and posts it themselves. + +That's it. No X API keys, no session cookies, no browser automation. Just content generation. + +## Content Pipeline + +### Step 1: Generate + +Hermes picks a topic from the security content pool (`~/.hermes/scripts/security-content-generator.py`) or generates a fresh take on a recent exploit. + +Content types: +- **Single tweet** — one vulnerability insight, under 280 chars +- **Thread** — 3-8 tweets breaking down an exploit, with hook + value + CTA + +### Step 2: Deslop + +All content passes through the deslop pipeline before being shown to the user: +- Zero em dashes +- Contractions everywhere +- Varied sentence rhythm +- No AI vocabulary (robust, leverage, navigate, etc.) +- Opinions allowed +- Rough edges preserved + +### Step 3: User Posts + +Hermes sends the content to the user via Telegram. The user: +- Copies the content +- Pastes it into X/Twitter +- Posts it manually + +No automation. No API keys needed. The user stays in full control. + +## Content Storage + +- Generated content: `~/.hermes/cron/output/security-thread_*.txt` +- Sent threads log: `~/.hermes/scripts/sent-threads.json` (prevents duplicates) + +## Workflow Files + +| File | Purpose | +|------|---------| +| `skills/hermes-integration/SKILL.md` | This file — integration guide | +| `skills/content-posting/SKILL.md` | Posting scripts and selectors (for reference) | +| `skills/viral-thread-generation/SKILL.md` | Thread structure and hooks | +| `skills/engagement-interaction/SKILL.md` | Like, reply, bookmark automation | +| `skills/algorithm-cultivation/SKILL.md` | Feed training and growth | + +## Safety Rules + +1. **Never auto-post.** The user posts all content manually. +2. **Never commit `.env` files or session cookies** (for when automation is added later) +3. **Always deslop content before showing the user** +4. **Log all sent content to prevent duplicates**