Reddit Account Operations

Operating doctrine for Reddit account automation — careful, helpful, non-spam contributor pattern with role separation, post qualification, quotas, anti-spam triggers and recovery. Use this for any scheduled Reddit activity (cron, agent, recurring task) where account safety, sub-mod tolerance and long-term reputation matter more than raw output.

Audits

Pending

Install

openclaw skills install reddit-account-operations

Reddit Account Operations

This skill is the operating doctrine for every Reddit automation run on a brand, professional or personal account.

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.

Drop-in for any niche (legal, medical, software, finance, creator, ecommerce). Replace the placeholders in section 0 with your own values.


0. Configure for your brand

Before running anything, fill these placeholders in your local copy or your agent's memory:

PlaceholderExampleYour value
<BRAND_NAME>"Acme Studio"
<BRAND_DOMAIN>"acme.studio"
<REDDIT_USERNAME>"u/AcmeAlex"
<BROWSER_PROFILE>"reddit-live"
<BROWSER_PORT>"9223"
<NICHE_KEYWORDS>"retrait permis OR contester amende"
<TARGET_SUBS>"r/conseiljuridique, r/AskFrance"
<WORKSPACE_DIR>"~/.openclaw/workspace/reddit-<brand>"

All shell snippets below assume an OpenClaw browser CLI bound by CDP, but the doctrine works with any browser-automation stack (Playwright, Puppeteer, Chrome MCP). Swap the CLI calls for your own.

Quick config (copy-paste YAML)

If your agent reads config from YAML, drop this in <WORKSPACE_DIR>/config.yaml:

brand:
  name: <BRAND_NAME>
  domain: <BRAND_DOMAIN>

reddit:
  username: <REDDIT_USERNAME>        # e.g. "u/AcmeAlex"
  browser_profile: <BROWSER_PROFILE> # e.g. "reddit-live"
  browser_port: <BROWSER_PORT>       # e.g. 9223

discovery:
  niche_keywords: <NICHE_KEYWORDS>   # e.g. "retrait permis OR contester amende"
  target_subs:
    - r/<sub-1>
    - r/<sub-2>

workspace:
  dir: <WORKSPACE_DIR>               # e.g. "~/.openclaw/workspace/reddit-acme"

alerts:
  channel: telegram | slack | discord
  webhook: <YOUR_WEBHOOK_URL>

Compatibility

The skill is markdown — it works wherever an agent reads SKILL.md:

StackSkill install path
Claude Code~/.claude/skills/reddit-account-operations/
OpenClaw~/.openclaw/skills/reddit-account-operations/
ClawHub-publishedone-click install via clawhub.ai
Cursor / Copilot CLIdrop SKILL.md into your project's .cursorrules or AGENTS.md
Any LLM agent reading markdown rulesconcatenate SKILL.md into your system prompt

1. Browser architecture

Physical profile

A single browser profile is used per account:

  • <BROWSER_PROFILE> (CDP direct, attached to http://127.0.0.1:<BROWSER_PORT>)

User data dir: ~/.openclaw-browser-profiles/<BROWSER_PROFILE>.

Use it through the OpenClaw browser CLI:

openclaw browser --browser-profile <BROWSER_PROFILE> status
openclaw browser --browser-profile <BROWSER_PROFILE> tabs
openclaw browser --browser-profile <BROWSER_PROFILE> navigate https://www.reddit.com/
openclaw browser --browser-profile <BROWSER_PROFILE> snapshot --limit 160
openclaw browser --browser-profile <BROWSER_PROFILE> click <ref>
openclaw browser --browser-profile <BROWSER_PROFILE> type <ref> "text"
openclaw browser --browser-profile <BROWSER_PROFILE> press Enter
openclaw browser --browser-profile <BROWSER_PROFILE> evaluate --fn "<async function>"

evaluate --fn is the primary API tool: it runs JS in the active tab and returns the function's value as JSON. Use it for /api/me.json, /api/comment, /api/submit, /api/selectflair, /r/<sub>/rising.json, /search.json.

Roles (mental separation, single physical profile)

Role: red-post

Account cockpit. Use for direct account action.

Use for:

  • original informative posts (text/self)
  • replies on threads
  • inbox/notifications check
  • profile checks
  • karma snapshots
  • flair application

Default page: https://www.reddit.com/user/<REDDIT_USERNAME without u/>

Mental model: act as the account. Protect it. Do not clutter it.

Role: red-engage

Search and discovery radar. Use to find what deserves action.

Use for:

  • keyword searches across target subs
  • monitoring rising/new posts in target subreddits
  • finding qualified candidates for replies
  • competitor observation
  • trend discovery

Default page: https://www.reddit.com/search/?q=<NICHE_KEYWORDS_URL_ENCODED>&type=link&t=day&sort=new

Mental model: discover, qualify, decide. Do not post impulsively from discovery.

Role: red-stealth

Quiet maintenance bay. Use for low-noise maintenance.

Use for:

  • subscribing to relevant subreddits
  • saving posts for later study
  • reading without interacting
  • sub-state observation (flair requirements, karma requirements, mod messages)

Default page: https://www.reddit.com/

Mental model: maintain quietly. No noisy engagement.

Operational law

  • red-post = act as the account
  • red-engage = discover what to react to
  • red-stealth = maintain quietly
  • stability matters more than speed
  • after every run, navigate back to the role's default page (resting state)

Never collapse all workflows into chaotic browsing.


2. Login verification (run first on every cron)

openclaw browser --browser-profile <BROWSER_PROFILE> status
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}; }"
  • If status is stopped: report the blockage in your recap channel and stop. Do not attempt to relaunch Chrome from inside a cron — that's a user-side action.
  • If name is null: login expired. Stop and report.

3. Phase gating (karma)

Reddit's spam filters and most sub auto-mods judge new accounts harshly. Run in two phases:

  • Phase A (karma < 100): only karma-builder + ops crons run. Any brand-mentioning cron must check karma at start and abort with "phase A, karma=X, skip" if karma < 100.
  • Phase B (karma ≥ 100): all crons authorized.

Always read <WORKSPACE_DIR>/memory/reddit-karma-log.md at start (last line = current state) AND verify via /api/me.json.

A Daily Metrics Recap cron appends a snapshot every night and pings your alert channel explicitly when karma crosses 100 for the first time.

Manual override (advanced)

You can force Phase B before karma ≥ 100 by appending a line YYYY-MM-DD - karma=X - phase=B (manual override) to reddit-karma-log.md. The override line takes priority over the threshold. Use when:

  • You have an established brand and want immediate brand-aware posting despite low karma.
  • You accept the risk of more automod removals on early posts (auto-freeze on 2 removals still applies — see §10).

Document the decision in reddit-learnings.md so future runs know why the threshold was bypassed.


4. Qualification of a post for reply

A post is repliable only if all of:

  • Age ≤ 24h (use created_utc)
  • Comment count < 200
  • Score positive (≥ 1, accept controversial-but-genuine)
  • Not flagged removed or locked
  • Question is a real question in your domain (not a vent, not a meme, not a request for free work)
  • No more than 1 expert-like reply already in top 10 comments (check for domain markers in flairs/body)
  • Subreddit is not in freeze state (see reddit-subs-state.md)
  • Your account has not interacted with this thread before (reddit-reply-log.md)
  • Phase A: no domain-expert reply at all — only general helpful Phase A comments in Phase A subs.

If any check fails: skip. Document why in the recap.


5. Reply templates

Phase A (karma builder, NO brand mention)

  • 1-3 sentences, conversational, genuinely helpful
  • Match the sub's tone
  • Never expert-grade advice (medical, legal, financial)
  • Never link to anything
  • Never sign with anything that hints at a profession

Example structure:

[Direct answer or empathy hook]. [One concrete tip from common sense]. [Soft close optional].

Phase B (brand-aware, expert)

Default mode = pedagogical, not promotional.

Structure:

[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 themselves: deadline, document to gather, official portal, command to run.]

[Optional: if the case is complex, mention that a specialist can review the OP's situation. No brand name in the comment body.]

Brand link policy — ZERO outgoing links to <BRAND_DOMAIN> (or any owned domain) in any reply or post. Indirect signaling only (mention a profession, never a brand name or URL). Reddit's automod and most subs flag self-promo aggressively — a single brand URL is enough to get a thread removed or trigger a sub ban.

  • The username profile is your only allowed brand signal (curious readers click through; no need to push).
  • No link in the comment body, not even in a trailing line.
  • No link in a footer / signature block.
  • No mention of the brand by name.

Forbidden in any reply:

  • Any URL on <BRAND_DOMAIN> (and all variants: www., subdomains, shorteners).
  • "Contact me", "DM me", "check our site", "more info here", phone numbers, email addresses.
  • Brand name in the comment body.
  • Promises ("you will win", "it's certain", "guaranteed results").
  • Quoting specific past client/customer cases.
  • Asking the OP to DM you.

6. Informative post structure (regular cadence, e.g. Tue + Fri)

Target sub: pick one from <TARGET_SUBS> based on:

  1. Sub karma requirement satisfied
  2. Sub freeze state (skip if frozen)
  3. Topic relevance (consult reddit-ideas.md and rotate)
  4. Last 14 days have NOT seen you post in that sub (cross-check reddit-post-log.md)

Format:

Title: [Question-form or "Guide:" prefix, ≤ 100 chars]

Body (markdown):
**Context** : [1 paragraph framing the problem people face]

**The rule / framework** : [2-3 paragraphs of plain-language explanation: sources, deadlines, mechanics]

**What to do concretely**:
1. [Action 1]
2. [Action 2]
3. [Action 3]

**Takeaway** : [1 paragraph summary]

---
*[Generic role tag, e.g. "Specialist in <field>"]. I don't take case-specific questions in public comments — for a precise situation, a 1:1 review with a qualified professional works better.*

ZERO brand link in the body, in the title, or in the closing block. The closing line is an indirect role mention only — no name, no URL, no contact info. Reddit treats brand domains as self-promo; a single URL is usually enough for automod removal in legal/medical/financial subs.

Apply flair if the sub requires one. If no relevant flair exists, skip the sub.


7. Quotas (hard limits)

ActionLimit
Replies / 24h (Phase B)3 max
Replies / Reply Pass run1-2 max
Informative posts / week2 max
Informative posts / day1 max
Subscribes / week5 max
Actions in same submin 6h apart
Actions globallymin 30 min apart
Karma builder comments / run1-2 max
Karma builder comments / day3 max

Quota tracking: read reddit-reply-log.md and reddit-post-log.md at start of every run, count entries with timestamps in the last 24h / 7d, abort early if quotas already met.


8. Anti-spam triggers (words and patterns to avoid)

Comment/post content

AvoidUse instead
"DM me", "contact me", "check our site", "more info here"(just don't ask, don't link)
<BRAND_NAME> in the comment body(no brand name in body)
"free consultation", "free first call"(no marketing)
Phone number, email(never)
Emojis(most professional/legal/medical subs are sober)
All caps for emphasis(use italics/bold sparingly)
Any URL on <BRAND_DOMAIN> (and www., subdomains, shorteners)never, in any reply or post
Multiple external links of any kindmax 1 external link total per post (never in replies)
bit.ly / tinyurl / shortenersbanned — Reddit flags these as spam directly

Behavioral triggers

  • Same content cross-posted < 7 days apart → spam detection
  • ≥ 2 links in a single comment → auto-removed
  • New account (karma < 100) posting in large subs → auto-removed
  • Replying within 60s of post creation → looks bot-like, wait ≥ 5 min
  • Same opening phrase across multiple replies → flagged
  • 3 actions in 30 min → temporary rate limit


9. Human-like posting flow (anti-CAPTCHA)

Reddit's /api/submit endpoint is gated behind reCAPTCHA Enterprise Invisible (sitekey 6LfirrMoAAAAAHZOipvza4kpp_VtTwLNuXVwURNQ at the time of writing). Posting purely via API will fail silently or get blocked. The reliable path is a human-like UI flow through the browser CLI: dwells, slow typing, reading pauses — enough behavioral signal to score above reCAPTCHA's threshold and let the post through.

Flow

  1. Pre-flight session check/api/me.json returns a non-null name.
  2. Navigate to the sub feed — let it load (≥ 1.5 s dwell).
  3. Human scroll — scroll the sub feed for 4-7 s to simulate reading.
  4. Navigate to /r/<sub>/submit — wait for composer ready.
  5. Find the title field via UI ref (the localized label, e.g. "Title" / "Titre"), type slowly (50-120 ms/key with jitter), then 0.8-1.5 s pause.
  6. Find the body field via UI ref ("Body" / "Champ de texte du corps de la publication"), type slowly, 0.8-1.5 s pause.
  7. Review pause — 3-7 s simulating proof-reading.
  8. Re-snapshot the UI — the Publish button transitions disabled → enabled once the fields are filled, so its ref changes. Always re-snapshot before clicking.
  9. Click Publish once, then wait for redirect to /comments/<id>/ (≤ 30 s).

Total flow: ~6 minutes per post. Slower is the point — speed is what trips the captcha.

Exit codes (recommended convention for your script)

CodeMeaningRecap action
0Published, URL on stdoutstatus: ok, log post URL
1Fatal error (UI ref missing, empty body)status: error, attach screenshot
2CAPTCHA visible mid-flowstatus: blocked, fall back to "draft to alert channel for manual publish"
3Session / login KOstatus: blocked, alert user to re-login

Gotchas (real ones, costly to discover)

  • LC_NUMERIC trap on macOS: locales like fr_FR.UTF-8 format decimals as 0,123 instead of 0.123. sleep and awk reject the comma → all dwells fall back to 0 → typing becomes instant → captcha fires immediately. Force LC_ALL=C in any helper that does fractional-second math. First time this bites you, you'll think your script is correct because no error is raised; the post just gets removed.
  • Re-snapshot before clicking Publish: the Publish button's UI ref changes when it transitions from disabled to enabled. Stale refs = wrong click target.
  • Localize the field labels: the labels Title / Body / Publish are localized server-side based on the account language. Either pin the account UI to English or maintain a label-map (FR/EN/etc.) and try both in find_ref_named.
  • Cron timeout: bump the per-job timeout to at least 1200 s for posting crons — a 60-120 s default will kill a successful flow.
  • Save debug artifacts: screenshots + page snapshots at each step in a scratch dir (e.g. /tmp/<your-namespace>/reddit-post/). They are gold when a post silently fails.
  • Reply Pass doesn't need this — replies use a different code path and do not currently trigger reCAPTCHA Enterprise. Only top-level post creation is gated.

When the UI changes

Reddit ships UI changes regularly. When find_ref_named starts returning null on labels that used to work:

  1. Take a manual snapshot via your browser CLI.
  2. Inspect the new label string for Title / Body / Publish.
  3. Update the label map.
  4. Re-test on r/test (safe, no consequence) before re-enabling the live posting cron.

10. Sub state management

File: <WORKSPACE_DIR>/memory/reddit-subs-state.md

For each sub, track:

  • Last action timestamp (any reply or post)
  • Last 5 actions and their outcome (live / removed / locked)
  • Karma requirement observed
  • Flair required (yes/no/list)
  • Freeze state (yes if 2 last actions were removed → unfreeze date = removal date + 7 days)
  • Mod messages received (any DM from /r/[sub] mods → flag for human review)

Update at the end of every run that touched the sub.


11. Recovery & blockers

IssueAction
status: stoppedReport in recap: "Chrome <BROWSER_PROFILE> stopped, user action required (relaunch Chrome on port <BROWSER_PORT>)". Stop.
name: null from /api/me.jsonReport login expired. Stop.
HTTP 429Stop the run, report "rate limited", wait next scheduled run.
HTTP 403 on POSTLikely modhash expired — re-fetch from /api/me.json once, retry once. If still 403: report and stop.
Captcha / challenge pageStop. Never attempt to solve. Report for user action.
result.json.errors contains RATELIMIT, DOMAIN_BANNED, BAD_CAPTCHA, SUBREDDIT_NOEXIST, USER_BLOCKEDTranslate the error in the recap, do not retry, freeze the sub if it's a sub-level error.
Comment posted but not visible in user profile after 5 minPossible shadowban. Flag for human verification (open profile in incognito).
Post removed by automod < 30 min after publishAuto-freeze sub for 7 days. Append to reddit-learnings.md.
evaluate returns null with no errorPage is not on reddit.com → navigate first, retry once.

12. Mandatory recap (alert channel + memory)

At the end of each cron:

Alert channel (Telegram / Slack / Discord) — final run message:

[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]

Memory — append to <WORKSPACE_DIR>/memory/reddit-recaps.md:

## YYYY-MM-DD HH:MM TZ — <job-id> — status: <status>
- Job: <description>
- Phase: A|B
- Karma: link=X comment=Y total=Z
- Actions: <list or "no action — reason">
- Subs touched: <list>
- Links: <URLs>
- Blockers: <text or "—">
- Next useful action: <1 line>

If no action was taken: say so clearly (no post/reply/follow/subscribe performed, reason).


13. Memory files inventory

Located at: <WORKSPACE_DIR>/memory/

FilePurposeUpdate cadence
reddit-recaps.mdPer-run logs (mandatory append)Every cron run
reddit-post-log.mdInformative posts (sub, URL, date, score)Each informative post run
reddit-reply-log.mdReplies sent (thread URL, comment URL, sub, date, removed?)Each reply pass
reddit-karma-log.mdDaily karma snapshot + phaseDaily Metrics Recap
reddit-subs-state.mdPer-sub freeze, flair, karma reqAfter any sub-touching action
reddit-ideas.mdContent backlog for informative postsWeekly Planning + ad hoc
reddit-learnings.mdPatterns observed (what got upvoted / removed)Weekly Planning + ad hoc

14. Account identity guardrails

This account exists to be useful in public with the brand as a background signal.

  • The username should be intentionally neutral — do not advertise the brand in the handle
  • Profile bio: a short generic line, no firm name, no contact info
  • Never reply to a DM that asks for expert-grade advice — direct the person to the brand contact page via a standard polite reply
  • Never share private case details, names, or numbers
  • Never reuse strict templates from your CRM / case management as Reddit content
  • Never promise an outcome
  • Never charge or solicit payment via Reddit

If anyone DMs about hiring you: reply once with a neutral line ("the studio takes inquiries via <BRAND_DOMAIN>/contact") and stop.


15. Phase A → Phase B transition

When the Daily Metrics Recap detects total_karma ≥ 100:

  1. Append to reddit-karma-log.md: YYYY-MM-DD - karma=X - PHASE_B_THRESHOLD_REACHED
  2. Send a distinct alert: 🎉 Reddit karma ≥ 100 — enable Phase B (jobs.json: keyword-monitor-* + reply-pass-* + informative-post-* + subscribe-growth — flip enabled=true)
  3. Do NOT auto-flip the crons (manual user action — reduces risk of premature B-phase posting)

Once Phase B is enabled by the user:

  • First week: 1 reply/day max (not the full 3) — soft ramp
  • Keep karma builder running for 2 more weeks in parallel
  • Once total_karma ≥ 250: disable karma builder, keep only Phase B crons

16. Stability discipline

  • Read the UI before clicking
  • One click → verify with a snapshot
  • Do not stack clicks
  • Close stale tabs at the end of every run
  • Return to the role's default page when done
  • Never silently fake a successful action — always verify via API or UI confirmation

Better silence than spam. Better a blockage report than a fake success.


17. First-run checklist

Before enabling any cron, run through this checklist:

  • Section 0 placeholders filled in your local copy / agent memory.
  • Reddit account created with neutral username (no brand in the handle).
  • Profile bio is one short generic line — no firm name, no contact info.
  • Browser profile launched at http://127.0.0.1:<BROWSER_PORT> and logged in.
  • /api/me.json returns a non-null name (login verified).
  • <WORKSPACE_DIR>/memory/ directory exists with the 7 memory files (see section 13) — empty is fine, scripts append to them.
  • Alert channel (Telegram / Slack / Discord) webhook tested with a "hello" message.
  • Phase A confirmed: total_karma < 100 → only karma-builder + ops crons enabled.
  • At least 2 weeks of organic activity (subscribes, low-stakes comments) before enabling brand-mentioning crons, even if karma ≥ 100.

A bash one-liner to init the memory files:

mkdir -p "<WORKSPACE_DIR>/memory" && cd "$_" && touch reddit-recaps.md reddit-post-log.md reddit-reply-log.md reddit-karma-log.md reddit-subs-state.md reddit-ideas.md reddit-learnings.md

(The GitHub repo ships an init-memory.sh script that does the same interactively.)


18. FAQ

Q: Do I need OpenClaw to use this skill? A: No. OpenClaw browser CLI is the example stack — the doctrine works with Playwright, Puppeteer, Chrome MCP, or any CDP-capable tool. Swap the CLI calls.

Q: Can I use this skill for multiple Reddit accounts? A: Yes — clone the workspace dir per account. Each account gets its own memory/ and its own browser profile. Do not cross-link accounts in any reply.

Q: What if my niche has only one relevant sub and it's strict? A: Run Phase A on adjacent subs (low-stakes, high-volume) to build karma, then start Phase B on the niche sub with the longest possible runway. Some niche subs also require 90+ days of account age regardless of karma.

Q: Is shadowban detection reliable? A: Partially. The "comment posted but invisible in incognito after 5 min" check catches most shadowbans, but Reddit also does community-specific shadowbans that don't fire that signal. Track per-sub upvote ratios over time as a backup signal.

Q: Can I run multiple crons in parallel? A: Yes, but respect the global "30 min apart" rule across all crons. A lock file at <WORKSPACE_DIR>/.lock is the cleanest way to enforce it.

Q: What if my account is suspended? A: Stop everything. Do not appeal automatically. Manual review only. Document the suspension in reddit-learnings.md with the exact last action before suspension.