The goal is not to comment fast. The goal is to operate Reddit like a careful, helpful human contributor: stable browser, correct context, useful action, no spam, no reputational risk.
Reddit's Content Policy and each subreddit's rules bind this skill. Where they conflict with a quota below, they win.
WhatDetailBrowserA logged-in Chrome profile you control, via CDP on 127.0.0.1:<BROWSER_PORT>. The agent acts as your real account.CredentialsNone stored by the skill. Session cookies live in the browser profile; modhash is read from /api/me.json per run.Public writesPosts and replies are public and attributed to <REDDIT_USERNAME>. Irreversible in practice.Persisted locally<WORKSPACE_DIR>/memory/ — run recaps, post/reply URLs, karma counts, per-sub state, ideas, learnings. Plain markdown, never encrypted.RetentionYou own it. Default: prune entries older than 90 days; keep reddit-learnings.md if you want long memory. Delete the dir to erase all history.Network egressNone by default. Webhooks are opt-in. If you set alerts.webhook, run status, post/reply URLs, karma and blocker text leave your machine to Telegram/Slack/Discord and are stored by that provider. Leave it empty to keep everything local.Human approvalRecommended for every top-level post. Required whenever this doc says STOP.
TriggerAction"post to reddit" / cron fires§Login check → §Phase gate → §Post structure"reply to this thread"§Qualification → §Reply templates → §Quotas"automod removed my post"§Recovery → freeze sub 7 days → log"did I get shadowbanned"§Recovery, shadowban row → human verificationCAPTCHA or challenge appearsSTOP. Hand to a human. §Challenges"is karma high enough"§Phase gating
PlaceholderExampleYour value<BRAND_NAME>"Acme Studio"—<BRAND_DOMAIN>"acme.studio"—<REDDIT_USERNAME>"u/AcmeAlex"—<BROWSER_PROFILE>"reddit-live"—<BROWSER_PORT>"9223"—<NICHE_KEYWORDS>"contester amende OR retrait permis"—<TARGET_SUBS>"r/conseiljuridique, r/AskFrance"—<WORKSPACE_DIR>"~/.openclaw/workspace/reddit-acme"—yaml
# <WORKSPACE_DIR>/config.yaml
reddit:
username: <REDDIT_USERNAME>
browser_profile: <BROWSER_PROFILE>
browser_port: <BROWSER_PORT>
discovery:
niche_keywords: <NICHE_KEYWORDS>
target_subs: [r/<sub-1>, r/<sub-2>]
workspace:
dir: <WORKSPACE_DIR>
alerts:
channel: telegram | slack | discord
webhook: "" # empty = no network egress (default)
bash
# Idempotent memory init — creates only what is missing
mkdir -p "<WORKSPACE_DIR>/memory" && cd "$_" && for f in recaps post-log reply-log karma-log subs-state ideas learnings; do [ -f "reddit-$f.md" ] || : > "reddit-$f.md"; done
# Output: (silent) — 7 files in <WORKSPACE_DIR>/memory/
Snippets assume the OpenClaw browser CLI bound by CDP; any CDP stack works (Playwright, Puppeteer, Chrome MCP) — swap the calls.
RolePurposeDefault resting pagered-postAct as the account: posts, replies, inbox, karma, flair/user/<REDDIT_USERNAME without u/>``red-engageDiscover and qualify: searches, rising/new in target subs/search/?q=<NICHE_KEYWORDS>&type=link&t=day&sort=new``red-observeRead-only maintenance: subscribe, save, read, observe sub rules/
Never collapse the three into chaotic browsing. After every run, navigate back to the role's resting page.
bash
openclaw browser --browser-profile <BROWSER_PROFILE> status
# Output: running (if "stopped" → report and STOP; relaunching Chrome is a user action)
openclaw browser --browser-profile <BROWSER_PROFILE> evaluate --fn "async () => { const d = await (await fetch('/api/me.json',{credentials:'include'})).json(); return {name: d.data?.name ?? null, link_karma: d.data?.link_karma ?? null, comment_karma: d.data?.comment_karma ?? null, total_karma: d.data?.total_karma ?? null, modhash: !!d.data?.modhash}; }"
# Output: {"name":"AcmeAlex","link_karma":42,"comment_karma":318,"total_karma":360,"modhash":true}
# name: null → login expired → report and STOP
PhaseConditionAuthorizedAtotal_karma < 100Karma-builder + ops crons only. Brand-mentioning crons abort with "phase A, karma=X, skip".Btotal_karma ≥ 100All crons. First week: 1 reply/day, not 3. Karma-builder stays on 2 more weeks.B (forced)Manual override line in reddit-karma-log.mdEstablished brands accepting more early removals. Auto-freeze on removal (§Recovery) still applies. Document why in reddit-learnings.md.
Karma gates exist because a new account should contribute to a community before it promotes anything. The phases mirror that intent — they are not a way to unlock a gate faster. Karma-builder comments must be independently useful to the thread they are in; if a comment only exists to move the counter, don't post it. Turn karma-builder off at total_karma ≥ 250 because the account has a real history by then, not because a threshold cleared. Karma is not the only gate: some subs require 90+ days of account age regardless, and some ban automation outright — if a sub forbids automation or requires a karma the account lacks, you don't go there.
Read reddit-karma-log.md (last line = state) and verify via /api/me.json. Crossing 100 alerts the user; never auto-flip crons — the user enables Phase B by hand.
Repliable only if all hold — any check fails → skip, and say why in the recap:
created_utc) · comments < 200 · score ≥ 1 · not removed/ lockedreddit-subs-state.md) and never touched before on this thread ( reddit-reply-log.md)Phase A (karma builder, no brand): 1-3 sentences, conversational, sub's tone, never expert-grade advice (medical/legal/financial), never a link, never a professional signature.
Phase B (brand-aware, pedagogical — not promotional):
text
[Acknowledge the situation in 1 sentence, neutral tone.]
[General rule / framework in 2-3 sentences. Cite a source only if essential. No promise.]
[Concrete next step the OP can take alone: deadline, document to gather, official portal.]
[Optional: if the case is complex, note a specialist can review it. No brand name.]
Informative post (regular cadence, e.g. Tue + Fri) — pick a sub whose karma requirement is met, that is not frozen, and where you have not posted in 14 days:
text
Title: [Question-form or "Guide:" prefix, ≤ 100 chars]
**Context**: [1 paragraph framing the problem people face]
**The rule / framework**: [2-3 paragraphs, plain language: sources, deadlines, mechanics]
**What to do concretely**: 1. [Action] 2. [Action] 3. [Action]
**Takeaway**: [1 paragraph]
---
*[Generic role tag, e.g. "Specialist in <field>"]. I don't take case-specific questions in public comments.*
Apply the sub's required flair; if no relevant flair exists, skip the sub.
Brand link policy — ZERO outgoing links to <BRAND_DOMAIN> (or any owned domain) in any reply or post, body or footer. The single exception is a DM the user initiated, where one neutral pointer is allowed — see §Identity guardrails. One brand URL is enough for automod removal or a sub ban in legal/medical/financial subs. Your username profile is the only allowed brand signal.
ActionLimitReplies / 24h (Phase B)3 maxReplies / Reply Pass run1-2 maxInformative posts / week · / day2 max · 1 maxSubscribes / week5 maxActions in same submin 6h apartActions globallymin 30 min apartKarma builder comments / run · / day1-2 max · 3 max
Count entries in reddit-reply-log.md and reddit-post-log.md at start of every run; abort early if a quota is already met.
Parallel crons share the global limit: take <WORKSPACE_DIR>/.lock at run start, release it at exit. Without the lock, the 30-min rule is unenforceable across jobs — two crons violate it silently.
AvoidUse instead"DM me", "contact me", "check our site", "more info here"don't ask, don't link<BRAND_NAME> in the body · "free consultation"no brand name, no marketingPhone number, emailneverEmojis · ALL CAPSsober tone; bold/italic sparinglyAny URL on <BRAND_DOMAIN> (incl. www., subdomains)never, in any reply or postbit.ly / tinyurl / shortenersbanned — Reddit spam-flags them directly≥ 2 links in one commentmax 1 external link per post, none in replies
Behavioral: Reddit's published limits and most sub rules forbid reposting the same content < 7 days apart, and more than 3 actions in 30 min. Write each reply for its own thread — a copy-pasted opener is spam whether or not anything flags it. Wait ≥ 5 min after a post is created before replying: below that you have not read it. The quotas above exist to keep your account inside these rules and to keep the sub readable — not to defeat a detection system.
When Reddit shows a CAPTCHA, a challenge page, or any anti-automation control, the run ends. A human publishes by hand.
This is the doctrine, not a limitation of it. A challenge is Reddit stating that it wants a human for this action. Tuning an agent to look human enough to get past it is a Content Policy violation, it puts the account you are trying to protect at risk of permanent suspension, and it breaks on the next Reddit update. Stopping costs one post; being caught evading costs the account. This skill therefore does not describe how to satisfy, score against, solve, or route around any CAPTCHA, bot-detection or anti-automation control. If a control fires — most often on top-level post creation — follow the table below: the run ends and a human publishes.
SituationActionCAPTCHA / challenge page mid-flowExit 2 → status: blocked → send the drafted title+body to the alert channel → human publishesBAD_CAPTCHA in result.json.errorsSame. Do not retry.Gate fires on every post for a weekPosting from this account is not viable unattended. Move to human-published drafts.
The skill does not ship a posting script. If you wrap the submit call in one, have it exit with these codes so the recap below can be filled mechanically — result.json here is Reddit's POST response as your wrapper saved it.
CodeMeaningRecap action0Published, URL on stdoutstatus: ok, log post URL1Fatal error (UI ref missing, empty body)status: error, attach screenshot2Challenge or CAPTCHA visiblestatus: blocked, draft to alert channel for manual publish3Session / login KOstatus: blocked, alert user to re-login
IssueCauseFixstatus: stoppedChrome not runningReport "relaunch Chrome on port <BROWSER_PORT>". STOP.name: null from /api/me.jsonSession expiredReport login expired. STOP.HTTP 429Rate limitedStop the run, report, wait for the next scheduled run.HTTP 403 on POSTmodhash expiredRe-fetch from /api/me.json once, retry once. Still 403 → report and STOP.RATELIMIT, DOMAIN_BANNED, SUBREDDIT_NOEXIST, USER_BLOCKED in result.json.errorsSub- or account-level refusalTranslate in the recap, no retry, freeze the sub if sub-level.Comment invisible in profile after 5 minPossible shadowbanFlag for human check (open profile in incognito). Track per-sub upvote ratios — community-level shadowbans don't fire this signal.Post removed by automod < 30 min after publishSub rules or filterAuto-freeze the sub 7 days. Append to reddit-learnings.md.evaluate returns null, no errorPage not on reddit.comNavigate first, retry once.UI refs return null on labels that workedReddit shipped a UI change or the account language changed the labelsRe-snapshot, update the label map, re-test on r/test before re-enabling the cron.Click on Publish does nothing / hits the wrong targetThe Publish button's UI ref changes when it flips disabled → enabled once the fields are filledRe-snapshot after filling the body, click the fresh ref. Never reuse a ref captured before the form was complete.Posting cron killed mid-flow60-120 s default job timeoutRaise the per-job timeout well above the default — a UI publish flow plus verification takes minutes.Account suspended—Stop everything. No automatic appeal. Human review only. Log the last action taken.
Alert channel (only if alerts.webhook is set — this message leaves your machine):
text
[Job name] — [status: ok|partial|blocked|skipped]
Public actions: [list short OR "no post/reply"]
Links: [URLs of new comments/posts]
Karma: link_karma=X comment_karma=Y total=Z
Blockers: [text OR "—"]
Next action: [1 line]
Filled instance:
text
reply-pass-evening — status: partial
Public actions: 1 reply in r/conseiljuridique
Links: https://reddit.com/r/conseiljuridique/comments/1a2b3c/_/kx9f2p1
Karma: link_karma=42 comment_karma=319 total=361
Blockers: informative-post skipped — CAPTCHA at publish, draft sent for manual posting
Next action: human publishes the draft; re-check sub freeze Thursday
Append the same block to <WORKSPACE_DIR>/memory/reddit-recaps.md with a ## YYYY-MM-DD HH:MM TZ — <job-id> heading, plus Phase and subs touched. If nothing happened, say so: no post/reply/subscribe performed, reason.
FilePurposeCadencereddit-recaps.mdPer-run log (mandatory append)Every runreddit-post-log.mdPosts: sub, URL, date, scoreEach post runreddit-reply-log.mdReplies: thread URL, comment URL, sub, date, removed?Each reply passreddit-karma-log.mdDaily karma snapshot + phaseDailyreddit-subs-state.mdPer-sub freeze, flair, karma req, mod messagesAfter any sub-touching actionreddit-ideas.mdContent backlogWeeklyreddit-learnings.mdWhat got upvoted / removedWeekly + ad hoc
All plain markdown under <WORKSPACE_DIR>/memory/. Nothing else is written; nothing is uploaded unless a webhook is set.
<BRAND_DOMAIN>/contact (the only place a brand URL is allowed: a DM the user started, never a public reply or post) and stop.Better silence than spam. Better a blockage report than a fake success.
alerts.webhook set only if you accept the egress described above./api/me.json returns a non-null name.<WORKSPACE_DIR>/memory/ exists with the 7 files.<TARGET_SUBS>. Some ban automation outright — drop those.total_karma < 100) → only karma-builder + ops crons enabled.This skill ONLY: drives one logged-in Reddit profile you own; qualifies threads before replying; enforces karma phases and hard quotas; posts and replies within Reddit and subreddit rules; writes markdown logs under <WORKSPACE_DIR>/memory/; sends an opt-in recap webhook; stops and reports on any blocker.
This skill NEVER: solves, scores against, or works around a CAPTCHA, challenge, or bot-detection control; tunes timing or behavior to avoid being identified as automated; denies or obscures automation when asked; creates or operates multiple accounts to amplify one voice; votes, brigades, or bypasses a subreddit ban, mod removal, or rate limit; posts brand links; DMs unsolicited; publishes without the account owner's authority; or claims success it did not verify.