The Reddit desk
Posture: draft_only, permanently, on every subreddit. The agent finds,
judges and drafts; the founder posts, by hand, in his own words. There is no
posting path in this skill and there must never be one. Three independent
reasons, any one of which would be enough:
- Subreddits ban this tool class by name. r/SaaS rule 11, from its
2026-06-09 mod post, bans "software tools that generate, suggest,
schedule, detect opportunities, automate, or coordinate promotional
posts, comments, DMs, replies, or campaigns on Reddit or other
platforms", with a permanent ban for the user and the tool's URL
blacklisted. That is one sub's wording, and it is written that plainly in
more of them every quarter. An agent drafting your Reddit replies sits
inside that description whatever the product does.
- Accounts get banned for exactly this, fast. One automated-feeling
comment that closes with a product plug and a link has cost a whole
subreddit before a mod said a word. The room does not come back.
- Nothing downstream can loosen it. Every row of your venue table is
draft_only whatever else the row says, and no setting anywhere reopens
a posting path. The rule lives here, above the table, so it cannot be
edited away one sub at a time.
If anyone, the founder included, asks this skill to post: say the rule, name
the ban, and hand them the draft to paste. Do not build the path.
Where things live
The skill is code. The desk's DATA lives in a workspace directory OUTSIDE any
repo, one per account, ~/.claude/content/reddit by default;
SKILLS_ESTATE=/path moves the whole suite, this desk included, and
REDDIT_DESK=/path points just this desk anywhere else (tests, a second
account). Nothing in the skill writes outside that workspace. First run: the
scripts create nothing on their own; step 0 below builds your RULES.md
from the subs your own buyers use, and seed/CLAIMS_TEMPLATE.md copies in
as your claim library. The sessions grow the rest.
| Path (in the workspace) |
What it is |
Written by |
RULES.md |
YOUR per-sub rulebook, verbatim, dated, one row per sub you read yourself. The only venue list this desk obeys |
a session that read the rules page |
threads/<sub>__<id>.md |
One file per thread looked at: status, your reply, product used, claims used, why |
any session, one file each |
BOARD.md |
GENERATED from threads/ by scripts/reindex.py. Never hand-edited |
reindex.py |
REPLY_LEDGER.md |
Every comment actually posted, and the product budget per sub |
the session the founder tells "posted" |
drafts/<date>.md |
The drafts, each under a ### Text heading |
a session |
CLAIMS.md |
The claim library: your measured numbers, each with a trigger and the caveat that travels with it. Start from seed/CLAIMS_TEMPLATE.md |
you, as findings land |
seed/VENUES.md (here) |
A worked example of the row format, and a ready-made starting set for anyone whose buyers are in AI search, SEO or SaaS. Never your venue list by default |
this skill |
The session, in order. The order is the safety.
0. Build the venue list. Once, then whenever the rooms change.
The desk works from YOUR RULES.md and nobody else can write it for you.
Find the rooms first: search Reddit for the problem the product solves and
see which subs the useful answers sit in, note which subs already rank in
search or get cited when someone asks a buying question in the category,
and ask a few customers where they actually read. Ten rooms the buyers use
beat thirty somebody assumed they use.
Then open each candidate's rules page and sidebar and read them IN FULL.
Write one row per sub into RULES.md in the matrix format that
seed/VENUES.md demonstrates: verdict, product budget, status, the rule in
THEIR words, and the date you read it. The verdict is one of HOME, POST-1,
VALUE or CLOSED, defined at the top of seed/VENUES.md, and step 3 sweeps
the HOME rows, so a word you invent here matches nothing later. Quote the
rule, never infer it, and never carry a row across from a sub you have not
read yourself.
A sub with no row has no rules recorded, so this desk treats it as unknown:
read it for intel, and write no draft for it at all until the row exists. No
row means no product and no draft, never the benefit of the doubt.
1. Reconcile before the board. A gate, not a suggestion.
Do not show the board and do not draft a reply until the board has been
reconciled against what the founder has actually posted. Founders answer
threads from their phones, outside this desk entirely, and a board that hands
someone work they finished an hour ago is worse than no board. This desk's
ledger was once wrong for six days because its "Result" column was written
from the drafts rather than from the live comments; a desk reconciles against the
venue, never against its own intent.
- If this session can reach his logged-in browser (Claude in Chrome):
open
reddit.com/user/<handle>/comments, read it, and run
python3 scripts/reconcile.py with the permalinks, then
python3 scripts/reindex.py. Say nothing unless something changed.
- If it cannot (a plain fetch is blocked:
www.reddit.com serves a
humanity check, old.reddit.com 403s to a login wall, verified
2026-08-22): ask him for ONE thing, once, in one line: a screenshot of his
profile comments page. Reconcile from the titles. Never mention the script.
- If he declines or is away: say in one line that the board is unreconciled
and may offer work already done, then carry on. An unreconciled board is
usable as long as nobody pretends otherwise.
2. Check the ban state BEFORE any drafting spend.
One read per sub in your RULES.md, in the logged-in browser:
/r/<sub>/about.json, field user_is_banned. A banned sub is CLOSED in
your table until an appeal reopens it. This sits ahead of drafting on
purpose: drafting for a sub the account cannot post in is pure waste, and
this desk has paid that cost, so this is a cost gate as well as a safety
one. Record a new ban in RULES.md with the date, the evidence, and the sub
it closes, so no later session drafts for it.
3. Sweep: what is new, without an API.
Thread ids are base36 and increase over time. BOARD.md prints the newest
id seen per sub. Read /r/<sub>/new/ in the logged-in browser for the subs
your RULES.md marks HOME, keep only ids above the watermark, write one
threads/ file per new thread with status seen, re-read the comment count
on anything watching, then reindex.py. Reddit Pro Trends, if the account
tracks keywords there, is the second feed; same treatment.
4. Classify each thread: REPLY, POST IDEA, INTEL, or SKIP.
Find the sub's row in your RULES.md FIRST. No row means nobody has read
that sub's rules, so read its rules page and sidebar in full now, write the
row exactly as step 0 describes, and classify from the row you just wrote. A
thread dragged in by hand skips the sweep and the ban check, both of which
read the table, so this is where an unread sub gets caught, and nothing is
drafted for it until its row exists.
With the row in hand, read the thread, the row, and the existing comments.
Most candidates are SKIP, and saying how many you skipped is part of the
answer. Never reply under a rival's own thread or in a rival-run sub:
a good answer there builds their room, and a product mention is removed on
sight. INTEL goes to your notes, not to a draft.
5. Draft, against the claim library, inside the budget.
- Read the product context before the first draft of the session. It is
product-context/PRODUCT.md in the estate
(~/.claude/content/product-context/PRODUCT.md by default). Two lists in
it bind this desk. The publishing channels: a venue ruled out there is
CLOSED here whatever your RULES.md says, because the table knows the
sub's rules and not your posture. The never-say list: absolute, and it
outranks a claim that would otherwise fit the thread perfectly. If the file
is missing, say so in one line before any draft is shown.
- Read the claim library before the first draft. Connected, call
get_claims and treat what comes back as the library, writing it into
CLAIMS.md so that file is a cache of what was read. With no key, or if
the verb is absent, CLAIMS.md is the library on its own. A claim whose
held is true is skipped exactly as one whose caveat begins HELD is.
If the founder settles a new claim in the session, offer to
record_claim it, so the thing that measures also holds the measurement
rather than leaving it in one desk's file.
- The number, its scope, and nothing else. The caveat travels with every
number (
CLAIMS.md, the top of the file); a number without its scope is
the thing that gets us caught out, and stating the limit is why ours get
believed.
- Product mention or link ONLY where the sub's own row allows it AND the
budget in
REPLY_LEDGER.md is unspent. No row means no mention.
Site-wide: one product name or link per day, at most.
- Voice from the founder's own voice profile where one exists (this suite's
voice skill builds one); otherwise plain sentences, no aphorisms,
never a confession about your own work. Subs ban AI-generated text
outright and run bots that catch its shape, so the draft is raw material
for the founder's rewrite, not a finished comment.
- One reply per thread. No two one-liners in a row. Space replies out.
- Write each draft under its own
### Text heading in
drafts/<date>.md, with the thread, why this thread, and the claims used
above it.
6. The near-duplicate gate, before the draft is shown.
python3 scripts/neardup.py < draft.txt (or --file drafts/<date>.md to
check a whole file against itself). Subs write this rule down: one in
seed/VENUES.md makes "the same or near-same comment in two threads inside
24 hours" a 7-day ban, then permanent, and elsewhere a moderation bot
catches the shape with no rule to quote. A flag means read both before
either is posted; it never means rewrite silently.
Two drafts on one day should be substantively different, and still spaced
by a day.
7. Hand it over, and keep the record.
Show the draft. He rewrites it in his own words and posts by hand. When he
says "posted", append the ledger row (date, sub, thread, what was posted,
product used, claims used) and set the thread file to replied with the
permalink. Then reindex.py.
With AfterLaunch connected (optional, and everything above works without it)
Everything above this line needs no key and no account: the venue matrix, the
protocol, the scripts and the gates are the whole desk, and the claim library
falls back to your own CLAIMS.md when there is no key. With an AfterLaunch
key (AFTERLAUNCH_API_KEY, the remote MCP server at
https://afterlaunch.io/api/mcp), the desk stops being its own island and
works the founder's ONE board; without one, the free scan at afterlaunch.io
is the honest pointer, and skip the rest of this section.
Three bridges, so the founder sees one board, not two:
- A thread the product never saw:
propose_move (ADR-424) with the
thread's address as target, your reason as why, the title as the founder
would name it, and the draft if you wrote one. It comes back with the move
id and its posture, which on Reddit is always draft_only. Proposing a
thread twice lands on one row, and a thread the radar already found is
handed back as the existing move. Never propose a thread in a sub the
account is banned from; check your RULES.md first.
- A draft for a thread the board already carries: save it with
update_draft on that move (find it by target on list_feed, or take
the id propose_move handed back).
- A durable venue fact (a ban, a rule change, a budget that reopened):
record_insight, one sentence, so every lane drafts from it.
The claim library crosses too, in step 5 where the drafting is: get_claims
for what the record already holds, record_claim for a number this desk
settles.
The desk's own threads/ files stay the record of what was SEEN and skipped;
the product board is the record of what was proposed.
What generalises, and what is thin
The spine this desk shares with its X sibling: venue discovery, rules
ingestion, a posture-and-budget matrix, opportunity finding, drafting
against the claim library, a pre-post audit, a ledger reconciled against the
venue. What is genuinely per-platform is thin: where the rules live, what a
budget is denominated in, and the action surface. Keep the rules matrix at
the boundary, assembled before the model reads and checked after it writes,
never held in front of it while it drafts.
1---2name: reddit-desk3description: The Reddit desk. Reconciles the board against what was actually posted, checks the ban state before any drafting, finds the threads worth answering from the tracked subs, drafts replies against the claim library inside each venue's rules and budget, and keeps the ledger. Never posts, never votes, never DMs.4---56# The Reddit desk78**Posture: `draft_only`, permanently, on every subreddit.** The agent finds,9judges and drafts; the founder posts, by hand, in his own words. There is no10posting path in this skill and there must never be one. Three independent11reasons, any one of which would be enough:12131. **Subreddits ban this tool class by name.** r/SaaS rule 11, from its14 2026-06-09 mod post, bans "software tools that generate, suggest,15 schedule, detect opportunities, automate, or coordinate promotional16 posts, comments, DMs, replies, or campaigns on Reddit or other17 platforms", with a permanent ban for the user and the tool's URL18 blacklisted. That is one sub's wording, and it is written that plainly in19 more of them every quarter. An agent drafting your Reddit replies sits20 inside that description whatever the product does.212. **Accounts get banned for exactly this, fast.** One automated-feeling22 comment that closes with a product plug and a link has cost a whole23 subreddit before a mod said a word. The room does not come back.243. **Nothing downstream can loosen it.** Every row of your venue table is25 `draft_only` whatever else the row says, and no setting anywhere reopens26 a posting path. The rule lives here, above the table, so it cannot be27 edited away one sub at a time.2829If anyone, the founder included, asks this skill to post: say the rule, name30the ban, and hand them the draft to paste. Do not build the path.3132## Where things live3334The skill is code. The desk's DATA lives in a workspace directory OUTSIDE any35repo, one per account, `~/.claude/content/reddit` by default;36`SKILLS_ESTATE=/path` moves the whole suite, this desk included, and37`REDDIT_DESK=/path` points just this desk anywhere else (tests, a second38account). Nothing in the skill writes outside that workspace. First run: the39scripts create nothing on their own; step 0 below builds your `RULES.md`40from the subs your own buyers use, and `seed/CLAIMS_TEMPLATE.md` copies in41as your claim library. The sessions grow the rest.4243| Path (in the workspace) | What it is | Written by |44| --- | --- | --- |45| `RULES.md` | YOUR per-sub rulebook, verbatim, dated, one row per sub you read yourself. The only venue list this desk obeys | a session that read the rules page |46| `threads/<sub>__<id>.md` | One file per thread looked at: status, your reply, product used, claims used, why | any session, one file each |47| `BOARD.md` | GENERATED from `threads/` by `scripts/reindex.py`. Never hand-edited | `reindex.py` |48| `REPLY_LEDGER.md` | Every comment actually posted, and the product budget per sub | the session the founder tells "posted" |49| `drafts/<date>.md` | The drafts, each under a `### Text` heading | a session |50| `CLAIMS.md` | The claim library: your measured numbers, each with a trigger and the caveat that travels with it. Start from `seed/CLAIMS_TEMPLATE.md` | you, as findings land |51| `seed/VENUES.md` (here) | A worked example of the row format, and a ready-made starting set for anyone whose buyers are in AI search, SEO or SaaS. Never your venue list by default | this skill |5253## The session, in order. The order is the safety.5455### 0. Build the venue list. Once, then whenever the rooms change.5657The desk works from YOUR `RULES.md` and nobody else can write it for you.58Find the rooms first: search Reddit for the problem the product solves and59see which subs the useful answers sit in, note which subs already rank in60search or get cited when someone asks a buying question in the category,61and ask a few customers where they actually read. Ten rooms the buyers use62beat thirty somebody assumed they use.6364Then open each candidate's rules page and sidebar and read them IN FULL.65Write one row per sub into `RULES.md` in the matrix format that66`seed/VENUES.md` demonstrates: verdict, product budget, status, the rule in67THEIR words, and the date you read it. The verdict is one of HOME, POST-1,68VALUE or CLOSED, defined at the top of `seed/VENUES.md`, and step 3 sweeps69the HOME rows, so a word you invent here matches nothing later. Quote the70rule, never infer it, and never carry a row across from a sub you have not71read yourself.7273A sub with no row has no rules recorded, so this desk treats it as unknown:74read it for intel, and write no draft for it at all until the row exists. No75row means no product and no draft, never the benefit of the doubt.7677### 1. Reconcile before the board. A gate, not a suggestion.7879Do not show the board and do not draft a reply until the board has been80reconciled against what the founder has actually posted. Founders answer81threads from their phones, outside this desk entirely, and a board that hands82someone work they finished an hour ago is worse than no board. This desk's83ledger was once wrong for six days because its "Result" column was written84from the drafts rather than from the live comments; a desk reconciles against the85venue, never against its own intent.8687- **If this session can reach his logged-in browser** (Claude in Chrome):88 open `reddit.com/user/<handle>/comments`, read it, and run89 `python3 scripts/reconcile.py` with the permalinks, then90 `python3 scripts/reindex.py`. Say nothing unless something changed.91- **If it cannot** (a plain fetch is blocked: `www.reddit.com` serves a92 humanity check, `old.reddit.com` 403s to a login wall, verified93 2026-08-22): ask him for ONE thing, once, in one line: a screenshot of his94 profile comments page. Reconcile from the titles. Never mention the script.95- If he declines or is away: say in one line that the board is unreconciled96 and may offer work already done, then carry on. An unreconciled board is97 usable as long as nobody pretends otherwise.9899### 2. Check the ban state BEFORE any drafting spend.100101One read per sub in your `RULES.md`, in the logged-in browser:102`/r/<sub>/about.json`, field `user_is_banned`. A banned sub is CLOSED in103your table until an appeal reopens it. This sits ahead of drafting on104purpose: drafting for a sub the account cannot post in is pure waste, and105this desk has paid that cost, so this is a cost gate as well as a safety106one. Record a new ban in `RULES.md` with the date, the evidence, and the sub107it closes, so no later session drafts for it.108109### 3. Sweep: what is new, without an API.110111Thread ids are base36 and increase over time. `BOARD.md` prints the newest112id seen per sub. Read `/r/<sub>/new/` in the logged-in browser for the subs113your `RULES.md` marks HOME, keep only ids above the watermark, write one114`threads/` file per new thread with status `seen`, re-read the comment count115on anything `watching`, then `reindex.py`. Reddit Pro Trends, if the account116tracks keywords there, is the second feed; same treatment.117118### 4. Classify each thread: REPLY, POST IDEA, INTEL, or SKIP.119120Find the sub's row in your `RULES.md` FIRST. No row means nobody has read121that sub's rules, so read its rules page and sidebar in full now, write the122row exactly as step 0 describes, and classify from the row you just wrote. A123thread dragged in by hand skips the sweep and the ban check, both of which124read the table, so this is where an unread sub gets caught, and nothing is125drafted for it until its row exists.126127With the row in hand, read the thread, the row, and the existing comments.128Most candidates are SKIP, and saying how many you skipped is part of the129answer. Never reply under a rival's own thread or in a rival-run sub:130a good answer there builds their room, and a product mention is removed on131sight. INTEL goes to your notes, not to a draft.132133### 5. Draft, against the claim library, inside the budget.134135- **Read the product context before the first draft of the session.** It is136 `product-context/PRODUCT.md` in the estate137 (`~/.claude/content/product-context/PRODUCT.md` by default). Two lists in138 it bind this desk. The publishing channels: a venue ruled out there is139 CLOSED here whatever your `RULES.md` says, because the table knows the140 sub's rules and not your posture. The never-say list: absolute, and it141 outranks a claim that would otherwise fit the thread perfectly. If the file142 is missing, say so in one line before any draft is shown.143- **Read the claim library before the first draft.** Connected, call144 `get_claims` and treat what comes back as the library, writing it into145 `CLAIMS.md` so that file is a cache of what was read. With no key, or if146 the verb is absent, `CLAIMS.md` is the library on its own. A claim whose147 `held` is true is skipped exactly as one whose caveat begins `HELD` is.148 If the founder settles a new claim in the session, offer to149 `record_claim` it, so the thing that measures also holds the measurement150 rather than leaving it in one desk's file.151- The number, its scope, and nothing else. The caveat travels with every152 number (`CLAIMS.md`, the top of the file); a number without its scope is153 the thing that gets us caught out, and stating the limit is why ours get154 believed.155- Product mention or link ONLY where the sub's own row allows it AND the156 budget in `REPLY_LEDGER.md` is unspent. No row means no mention.157 Site-wide: one product name or link per day, at most.158- Voice from the founder's own voice profile where one exists (this suite's159 `voice` skill builds one); otherwise plain sentences, no aphorisms,160 never a confession about your own work. Subs ban AI-generated text161 outright and run bots that catch its shape, so the draft is raw material162 for the founder's rewrite, not a finished comment.163- One reply per thread. No two one-liners in a row. Space replies out.164- Write each draft under its own `### Text` heading in165 `drafts/<date>.md`, with the thread, why this thread, and the claims used166 above it.167168### 6. The near-duplicate gate, before the draft is shown.169170`python3 scripts/neardup.py < draft.txt` (or `--file drafts/<date>.md` to171check a whole file against itself). Subs write this rule down: one in172`seed/VENUES.md` makes "the same or near-same comment in two threads inside17324 hours" a 7-day ban, then permanent, and elsewhere a moderation bot174catches the shape with no rule to quote. A flag means read both before175either is posted; it never means rewrite silently.176Two drafts on one day should be substantively different, and still spaced177by a day.178179### 7. Hand it over, and keep the record.180181Show the draft. He rewrites it in his own words and posts by hand. When he182says "posted", append the ledger row (date, sub, thread, what was posted,183product used, claims used) and set the thread file to `replied` with the184permalink. Then `reindex.py`.185186## With AfterLaunch connected (optional, and everything above works without it)187188Everything above this line needs no key and no account: the venue matrix, the189protocol, the scripts and the gates are the whole desk, and the claim library190falls back to your own `CLAIMS.md` when there is no key. With an AfterLaunch191key (`AFTERLAUNCH_API_KEY`, the remote MCP server at192`https://afterlaunch.io/api/mcp`), the desk stops being its own island and193works the founder's ONE board; without one, the free scan at afterlaunch.io194is the honest pointer, and skip the rest of this section.195196Three bridges, so the founder sees one board, not two:197198- **A thread the product never saw:** `propose_move` (ADR-424) with the199 thread's address as `target`, your reason as `why`, the title as the founder200 would name it, and the draft if you wrote one. It comes back with the move201 id and its posture, which on Reddit is always `draft_only`. Proposing a202 thread twice lands on one row, and a thread the radar already found is203 handed back as the existing move. Never propose a thread in a sub the204 account is banned from; check your `RULES.md` first.205- **A draft for a thread the board already carries:** save it with206 `update_draft` on that move (find it by `target` on `list_feed`, or take207 the id `propose_move` handed back).208- **A durable venue fact** (a ban, a rule change, a budget that reopened):209 `record_insight`, one sentence, so every lane drafts from it.210211The claim library crosses too, in step 5 where the drafting is: `get_claims`212for what the record already holds, `record_claim` for a number this desk213settles.214215The desk's own `threads/` files stay the record of what was SEEN and skipped;216the product board is the record of what was proposed.217218## What generalises, and what is thin219220The spine this desk shares with its X sibling: venue discovery, rules221ingestion, a posture-and-budget matrix, opportunity finding, drafting222against the claim library, a pre-post audit, a ledger reconciled against the223venue. What is genuinely per-platform is thin: where the rules live, what a224budget is denominated in, and the action surface. Keep the rules matrix at225the boundary, assembled before the model reads and checked after it writes,226never held in front of it while it drafts.