social-autoposter
v1.2.0
Published
Automated social posting pipeline for Reddit, X/Twitter, LinkedIn, and Moltbook. Install as a Claude Code agent skill.
Maintainers
Readme
social-autoposter
Automated social posting pipeline for Reddit, X/Twitter, LinkedIn, and Moltbook. Ships as a Claude Code skill plus a set of standalone Python helpers and macOS launchd jobs.
Posts are written to a shared Neon Postgres database via DATABASE_URL in ~/social-autoposter/.env. Each platform drives its own persistent Playwright MCP browser profile, so logins survive across runs.
Prerequisites
A new machine needs all of these before the pipeline can run end to end:
- macOS (the launchd plists are mac-only; Linux users can crib the cron snippets from
setup/SKILL.mdStep 7) - Node.js 16+ (for
npx, the installer, and@playwright/mcpat runtime) - Python 3.9+ with
pip3(helper scripts;psycopg2-binaryis auto-installed by the installer) - Claude Code CLI on
PATH(the cron scripts shell out toclaude -pwith a per-platform MCP config) psqlonPATH(a few scripts query Neon directly)- One Chromium install per platform (created on first run by
@playwright/mcpagainst the persistent profile dirs)
Optional:
MOLTBOOK_API_KEYin.envfor Moltbook posting and scanningRESEND_API_KEYandNOTIFICATION_EMAILin.envfor DM-escalation emails
Install
npx social-autoposter initbin/cli.js does all of the wiring in one shot:
- Copies
scripts/,skill/,setup/,SKILL.md,schema-postgres.sql, andbrowser-agent-configs/into~/social-autoposter/ - Creates
config.jsonfromconfig.example.jsonand.envfrom.env.example(the shared NeonDATABASE_URLis pre-filled) - Installs
psycopg2-binaryviapip3if missing - Generates launchd plists in
~/social-autoposter/launchd/with the user's actualHOMEandPATH - Installs the Playwright MCP configs to
~/.claude/browser-agent-configs/(twitter, reddit, linkedin) with__HOME__and__NODE_BIN__placeholders substituted. Existing files are left alone, so any window-position tweaks survivenpx social-autoposter update. - Creates empty persistent browser profile dirs at
~/.claude/browser-profiles/{twitter,reddit,linkedin} - Symlinks
~/.claude/skills/social-autoposterand~/.claude/skills/social-autoposter-setupto the install dir
To refresh code without touching user files (config.json, .env, SKILL.md, or any browser config you customized):
npx social-autoposter updateConfigure
Tell your Claude Code agent: "set up social autoposter". The interactive wizard in setup/SKILL.md walks through:
- Verifying the Neon connection
- Filling in
~/social-autoposter/config.jsonwith handles for Reddit, Twitter, LinkedIn, optional Moltbook - A 5-question interview to draft your
content_angle - Capturing
projectswithtopics(used by the tiered reply strategy) - Verifying browser logins per platform via the dedicated MCP agent. The first time each platform runs you'll be asked to log in once; cookies persist into the userDataDir under
~/.claude/browser-profiles/. - A dry-run of
find_threads.py --limit 3 - Optional: loading the launchd plists into
~/Library/LaunchAgents/
How the runtime is wired
launchd ──▶ skill/run-{platform}.sh ──▶ claude -p --strict-mcp-config --mcp-config ~/.claude/browser-agent-configs/{platform}-agent-mcp.json
│ │
│ └──▶ @playwright/mcp@latest
│ │
│ └──▶ ~/.claude/browser-profiles/{platform}/ (persistent userDataDir)
│
├──▶ scripts/find_{tweets,threads}.py (no browser, API + DB dedup)
├──▶ scripts/pick_project.py (weighted project rotation)
├──▶ scripts/top_performers.py (feedback report from past stats)
└──▶ Neon Postgres (DATABASE_URL in .env)Each skill/run-*.sh:
- Controlled by launchd (load/unload). Use the dashboard Pause All / Resume All button, or
launchctl unload/loaddirectly - Acquires a per-platform lock from
skill/lock.sh(waits up to 60 min for any prior run) - Sources
~/social-autoposter/.env - Picks a project, builds a feedback report, fetches
llms.txtfor product context - Calls
find_*.pyfor API-side candidates already deduped against the DB - Spawns a child Claude process with
--strict-mcp-configso it only sees the one platform's browser MCP
The launchd schedules from bin/cli.js:
| Job | Cadence |
|-----|---------|
| com.m13v.social-autoposter (run.sh) | every 3600 s (hourly) |
| com.m13v.social-stats (stats.sh) | every 21600 s (6 h) |
| com.m13v.social-engage (engage.sh) | every 21600 s (6 h) |
Per-platform plists in launchd/ (twitter, reddit, linkedin, moltbook, github, octolens, audit, dm-replies, scan-replies, etc.) use either StartInterval or StartCalendarInterval for fixed wall-clock times. Activate them with:
ln -sf ~/social-autoposter/launchd/com.m13v.social-twitter.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.m13v.social-twitter.plistSkill commands
| Command | What it does |
|---------|-------------|
| /social-autoposter | Comment run: find threads, draft, post, log (cron-safe) |
| /social-autoposter post | Create an original post or thread (manual only) |
| /social-autoposter stats | Update engagement stats via API |
| /social-autoposter engage | Scan and reply to responses on our posts |
| /social-autoposter audit | Full browser audit of all posts |
View live stats at https://s4l.ai/stats/<your-handle> once posts start landing in Neon.
Repo layout
social-autoposter/
├── SKILL.md the playbook (locked, immutable)
├── bin/cli.js installer + dashboard launcher
├── browser-agent-configs/ Playwright MCP templates (twitter/reddit/linkedin)
├── config.example.json config template
├── schema-postgres.sql Neon schema
├── setup/SKILL.md interactive setup wizard skill (locked)
├── scripts/ Python and JS helpers (no browser, no LLM)
├── skill/ shell wrappers invoked by launchd
└── launchd/ generated macOS LaunchAgent plistsFor other AI agents
The skill works with any agent that has shell access, browser automation, and an LLM. The Python and JS helpers in scripts/ handle thread discovery, reply scanning, and stats updates without needing a browser. SKILL.md is the playbook; any agent can read it and execute the workflows with its own tools.
Pause and resume
Use the dashboard at localhost:3141 (Pause All / Resume All button), or manually:
# Pause: unload all jobs + kill running processes
for plist in ~/Library/LaunchAgents/com.m13v.social-*.plist; do launchctl unload "$plist"; done
# Resume: reload all jobs
for plist in ~/social-autoposter/launchd/com.m13v.social-*.plist; do
ln -sf "$plist" ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/$(basename "$plist")
done