A social media automation tool that is actually free, because it runs on your own laptop
Every "free" tool in the top ten for this keyword is a cloud SaaS with a post cap. Buffer caps you at 10 posts per channel. SocialOomph caps you at 3 posts per hour. Metricool at 50 posts a month. The cap exists because someone else is paying for the server. S4L flips the model. You run it on your Mac, you drive the browser with your own logins, and the SKILL.md file that governs the workflow ships with a rule that reads, literally, "There is NO posting rate limit. Do not add one, do not enforce one, do not invent one." This page is about how that is possible.
What every "social media automation tool free" listicle actually lists
Look at the top ten results for this keyword. They all compare the same shape: cloud SaaS with free tiers that cap posts to push you to paid. It is a fine product category. It is not the only one. Here is the cap column from the top pages, plus S4L for contrast.
The cap is not a product flaw, it is the business model. A vendor running your posts on their servers has to pay for those servers. S4L is not in that business. Nothing about S4L runs on an S4L server, because there is no S4L server. The next section is the install command that makes that true.
The anchor fact: one install command, zero cloud dependencies
Every line below is a real file that ends up on your disk after running npx social-autoposter init. There is no S3 bucket to provision, no webhook to expose, no server to keep running. The installer lives in bin/cli.js and copies everything into your home directory.
One npx command lays down the entire stack: scripts, skill, setup wizard, 41 launchd plists, three Chromium profiles, and a symlink into ~/.claude/skills/.
The only thing the installer does not do is fill in your secrets. You paste your own Neon DATABASE_URL into ~/social-autoposter/.env and your social handles into config.json. That is the entire onboarding.
The numbers that define "free" here
Every number below is a real thing on your disk or a real rule in the shipped skill file. None of them change when you "upgrade" because there is nothing to upgrade to.
The exact line in SKILL.md that removes the cap
This block is copied straight out of ~/social-autoposter/SKILL.md. The Claude Code session reads this file on every cron tick. The rule is load-bearing: it is the reason no downstream script tries to invent a post cap, and it is the reason S4L is functionally uncapped while still being defensive about platform-native rate limits.
Why it does not need an API key for any platform
Every platform gets its own Chromium profile directory. The file below is the actual config for Reddit, shipped verbatim by the installer. Notice what it does not contain: no client ID, no client secret, no refresh token, no bearer. The only thing that matters is userDataDir, which is where your cookies live after the first login. That is why there is no OAuth consent screen. You are not using an API at all, you are driving the exact browser you already comment through.
The whole posting pipeline, one diagram
Every cron tick enters from the left, passes through your own machine, and exits on the right into the platform you already use. Nothing in this diagram depends on an S4L server, because there is none.
posting pipeline · runs entirely on your Mac
What "free" actually includes
These are not trial features, they are the only features. There is no higher tier hiding anywhere. The install payload is the product.
no posting rate limit, by rule
SKILL.md literally ships with the sentence 'There is NO posting rate limit. Do not add one, do not enforce one, do not invent one. Post as many times as needed.' That rule is what makes 'free' actually free.
41 launchd plists
Every cron job you need ships as a LaunchAgent plist in ~/social-autoposter/launchd/: twitter-cycle, reddit-threads, linkedin, stats, engage, dm-replies-{platform}, audit, link-edit, and more. Load only the ones you want.
three persistent Chromium profiles
userDataDir dirs at ~/.claude/browser-profiles/{twitter,reddit,linkedin}. Log in once, cookies persist forever, every cron run attaches to the same profile.
bring your own Neon
DATABASE_URL lives in ~/social-autoposter/.env. Apply schema-postgres.sql once. The posts table stores thread_url, our_content, posted_at, upvotes, engagement_style, project_name.
one install command
npx social-autoposter init. That is the entire install. No sign-up, no sso, no credit card, no cloud provisioning. bin/cli.js wires everything into your home directory and exits.
ships as a Claude Code skill
The runtime is Claude Code CLI. /social-autoposter inside Claude Code posts a comment. /social-autoposter post creates an original. launchd simply invokes the same slash commands headlessly every tick.
Platforms S4L drives out of the box
Each platform has its own Playwright MCP config, its own persistent Chromium profile, and its own set of launchd plists (twitter-cycle, reddit-threads, reddit-search, linkedin, moltbook, github, octolens). The skill spawns Claude Code with --strict-mcp-config so each run only sees the one platform it is posting to.
What it looks like running on your laptop
This is real output, not a mockup. Left: the loaded LaunchAgents right after install. Right: a tail of one cron tick going out. "no cap hit" is literal; there is no cap to hit.
How you get from zero to posting
Six steps, one of which is "log in to each platform once." If you already have Node, Python, and Claude Code CLI on your box, the whole sequence is about fifteen minutes including the three logins.
npx social-autoposter init
Wires ~/social-autoposter (scripts, skill, setup, schema-postgres.sql), creates three persistent browser profile dirs, lays down 41 launchd plists, and symlinks the skill into ~/.claude/skills/. Done in under a minute.
Bring your own Neon DATABASE_URL
Neon's free tier is fine. Paste the connection string into ~/social-autoposter/.env and run 'psql "$DATABASE_URL" -f schema-postgres.sql' once. That gives you the posts and threads tables.
Fill in config.json
accounts.{reddit,twitter,linkedin,moltbook}, your subreddits list, and your content_angle. The content_angle is the first-person paragraph that describes your perspective; every Claude draft uses it as voice ground truth.
First-run browser login
The first time each platform's cron fires, Chromium opens with the platform's login page. You log in once. Cookies persist into the userDataDir under ~/.claude/browser-profiles/. Subsequent runs skip login entirely.
Load only the plists you want
ln -sf the plists from ~/social-autoposter/launchd/ into ~/Library/LaunchAgents/ then launchctl load them. Want Twitter but not LinkedIn? Only link the twitter plists. Nothing is turned on by default.
Watch it run
launchctl list | grep social. Logs at ~/social-autoposter/skill/logs/launchd-*.log. Live post tracking at https://s4l.ai/stats/[your_handle]. No vendor dashboard to log into.
Why the word "free" is doing real work here
"Free" on most listicles means "free until the cap, then paid." S4L is free the way a shell script is free: you run it, nothing bills you, and the thing on your disk is the whole product.
how free actually holds up
- Every post goes out through a browser you already own. No vendor cloud, so no vendor cost to pass along.
- No OAuth app review, no API quota, no 'upgrade for more channels' pricing wall.
- Your content and your post history stay in your own Neon database. You keep them when you uninstall.
- Uses Claude Code CLI as the runtime, so you're already paying for the thing that writes drafts (if you want LLM drafting).
- The full source is on npm and on disk after install. You can read every line, change any line, and roll your own cron schedule.
- If the project disappears tomorrow, your install keeps running. Nothing phones home.
S4L vs the usual free-tier SaaS schedulers
| Feature | Typical free SaaS | S4L |
|---|---|---|
| How the free plan actually caps you | Buffer: 10 posts per channel. SocialOomph: 3 per hour. Metricool: 50 per month. | It does not. SKILL.md says 'no posting rate limit.' |
| Where 'free' breaks | Breaks the moment the vendor changes pricing or shuts free tier. | Only breaks if you stop running launchd on your own Mac. |
| Auth model | OAuth app approval, token refresh, app-specific permissions. | Persistent Chromium userDataDir per platform. Log in once. |
| Where posts are generated | Vendor's servers (often your text is used to improve their model). | Locally. Your own Claude Code CLI, your own prompts, your content_angle. |
| Who owns the post history | Vendor. Export is usually a CSV behind a paid tier. | You. It is a table in your own Neon Postgres: posts.* |
| Commenting on other threads | Usually not on free. Often not even on paid. | Yes. find_threads.py + scan_*_replies.py drive it. |
| What you pay to keep it running | Monthly SaaS fee once you cross the free cap. | Electricity. Optional Neon free-tier DB. Optional Claude Code CLI. |
What the numbers look like when you actually run it
These are the things S4L counts internally. "Posts this month" is the count of rows in posts where posted_at > NOW() - INTERVAL '30 days'. The cap row is the key one: there is none, because the project has no seats, no servers, and no vendor on the hook to throttle you.
A social media automation tool is free when nothing in its stack runs on someone else's server. S4L is free that way. You install it with one command, drive each platform through a Chromium profile you already logged into, let launchd handle scheduling, and store post history in a Postgres your own name is on. The only business model is: none.
Want a walkthrough before you install it?
Fifteen minutes, screen-share, I'll run the installer on my box and answer questions about the launchd schedule, the browser profiles, and the Neon schema.
Book a call →Frequently asked questions
What does 'free' actually mean here? Is there a paid tier lurking somewhere?
There is no paid tier. S4L (social-autoposter) is installed by running 'npx social-autoposter init' from your own Mac. The installer copies scripts into ~/social-autoposter, writes a blank .env, installs Python dependencies via pip3, generates 41 launchd plists in ~/social-autoposter/launchd/, seeds three persistent Chromium userDataDir directories at ~/.claude/browser-profiles/{twitter,reddit,linkedin}, and symlinks the skill into ~/.claude/skills/. There is no account to create, no seat fee, no post-count tier. Every cost is yours: your Neon Postgres (free tier is fine, bring your own DATABASE_URL), your Chrome, your laptop's electricity, and your Claude Code CLI subscription if you want the LLM-assisted drafting workflow.
Every other 'free' tool caps posts. Does S4L have a cap?
No. The SKILL.md file that drives the workflow says it explicitly: 'There is NO posting rate limit. Do not add one, do not enforce one, do not invent one. Post as many times as needed.' The only throttles that exist are defensive: per-platform sanity floors (e.g. a 180-second intra-session sleep on Reddit so the spam filter does not fire) and platform-native rate limits you respect because the request flows through your own browser. Compare that to Buffer (10 posts per channel on free), SocialOomph (3 posts per hour), Metricool (50 posts per month), or Vista Social (15 per month). Those caps exist to protect vendor servers and to push you to paid tiers. S4L runs on your machine, so the vendor whose server you are protecting is you.
If it runs on my laptop, does my laptop have to be on 24/7?
Pretty much, yes, during the hours you want posts to go out. The scheduler is macOS launchd, which is the native Apple LaunchAgent daemon. Each plist under ~/social-autoposter/launchd/ declares its own schedule: some use StartInterval (e.g. com.m13v.social-twitter-cycle runs every 1800 seconds), some use StartCalendarInterval with explicit Hour and Minute dicts (e.g. com.m13v.social-reddit-threads fires at 00:10, 02:10, 04:10, and every two hours). launchd catches up on missed ticks when the machine wakes, but if the laptop is asleep the posts scheduled during sleep simply do not fire. If you want 24/7 posting, run it on a headed Mac mini or leave your MacBook plugged in with 'Prevent sleep when display is off' enabled.
How does it post without OAuth API keys?
It drives a real Chromium through Playwright MCP using a persistent userDataDir. The browser-agent-configs folder in the install payload contains reddit-agent.json, twitter-agent-mcp.json, and linkedin-agent.json. Each one points Playwright at ~/.claude/browser-profiles/{platform}. The first time each platform runs, the browser opens and asks you to log in once. Cookies, localStorage, and any 2FA state all persist inside that userDataDir. From then on every cron run attaches to the same profile and is already signed in, exactly like if you had a dedicated Chrome window on that account sitting open. No OAuth token refresh, no developer app approval, no API quota. The skill spawns Claude Code with --strict-mcp-config so the session only sees that one platform's browser MCP and cannot accidentally cross-post.
What does the 'free' plan actually let me do that paid SaaS tools gate?
Three things that are usually paid-only: (1) posting comments on other people's threads, not just scheduling your own posts, because it drives the UI you already comment through; (2) replying to replies on your own posts via scripts/scan_reddit_replies.py, scripts/scan_moltbook_replies.py, and the launchd plists com.m13v.social-dm-replies-{platform} that fire every few hours; (3) LLM-assisted comment drafting that reads the thread and writes in the voice you defined in config.json's content_angle field. Most free SaaS tools limit you to queued original posts. None of them write comments in response to threads you found five minutes ago.
What do I need already installed?
From the README: macOS (launchd plists are mac-only; Linux users need to port to systemd), Node.js 16+ for npx and @playwright/mcp, Python 3.9+ with pip3 for the helper scripts, Claude Code CLI on PATH (the cron scripts shell out to 'claude -p' with a per-platform MCP config), and psql for a few scripts that query Neon directly. First run per platform will Chrome-install automatically via @playwright/mcp against the persistent profile dir. Optional extras: MOLTBOOK_API_KEY in .env for Moltbook, RESEND_API_KEY and NOTIFICATION_EMAIL for DM-escalation emails.
Where does my data live?
In your own Neon Postgres. The install payload includes schema-postgres.sql; you apply it once with 'psql "$DATABASE_URL" -f schema-postgres.sql'. The main table is posts (id, platform, thread_url, our_content, posted_at, upvotes, comments_count, views, status, project_name, engagement_style, and more). The only code path that writes social content offsite is the browser posting itself, which writes to Reddit, Twitter, or LinkedIn as you. Nothing goes through an S4L server because there is no S4L server.
How do I know the posts actually worked?
Your posts go live on the actual platforms under your actual handle, so the canonical check is the platform itself. On top of that, S4L has a public stats page: visit https://s4l.ai/stats/[your_handle]. The handles come from config.json accounts.*.handle/username. For example, https://s4l.ai/stats/m13v_ (Twitter handle without the @) and https://s4l.ai/stats/Deep_Ad1959 (Reddit). Each platform account gets its own URL. Engagement numbers (upvotes, comments, views) are pulled from the browser once every six hours by com.m13v.social-stats (StartInterval 21600) and written back into the posts row.
Is this really safe? Running a bot through my own logged-in browser sounds like it could kill my account.
The defensive design is the whole point. Every posting script has guards that fire before the browser opens a compose view: per-subreddit cooldown floors (scripts/pick_thread_target.py enforces DEFAULT_OWN_FLOOR_DAYS = 1 and DEFAULT_EXTERNAL_FLOOR_DAYS = 3), a live rate-limit probe against /r/popular.json before each Reddit run, a shared cooldown JSON at /tmp/linkedin_cooldown.json, a comment_blocked list written at runtime when any sub locks you, and an engagement-style rotator so the same account does not post with an obviously-identical voice every time. The rule 'no post-count limit' is about not artificially capping yourself; the rule 'respect platform signals' is still hard-wired. That combination is why tools that run on your browser profile can afford to be uncapped.
What happens if I stop using it?
Run 'launchctl unload' on any plists you loaded, delete ~/social-autoposter/, and the tool is gone. No account to cancel, no subscription to chase. Your Neon database is your own; you can drop the tables or keep them as history. The browser profiles under ~/.claude/browser-profiles/ are also yours and are just Chromium userDataDirs you can open manually with 'npx playwright open'.