Reddit account cultivation for indie developers. Uses AppleScript to control real Chrome — undetectable by anti-bot systems. Checks karma, finds rising posts...
---
name: reddit-cultivate
description: Reddit account cultivation for indie developers. Uses AppleScript to control real Chrome — undetectable by anti-bot systems. Checks karma, finds rising posts, drafts comments, and posts directly. Triggers on "/reddit-cultivate", "check my reddit", "reddit maintenance", "find reddit opportunities", "build reddit karma".
license: Apache-2.0
homepage: https://canlah.ai
metadata:
author: Canlah AI
version: "1.0.2"
tags:
- reddit
- social-media
- macos
- automation
- applescript
- chrome
---
# Reddit Cultivation Skill (AppleScript Chrome Control)
Build and maintain Reddit presence by controlling the user's real Chrome browser via AppleScript. No Playwright, no Selenium, no API tokens.
---
## How It Works
```
Claude Code → osascript → Chrome (real browser, logged in) → Reddit
```
- AppleScript executes JavaScript in Chrome's active tab
- Chrome is already logged into Reddit → cookies sent automatically
- Same-origin fetch → no CORS, no detection, no IP blocks
- Reddit cannot distinguish this from human browsing
---
## Prerequisites
- **macOS only** (AppleScript is a macOS technology)
- Chrome: View → Developer → Allow JavaScript from Apple Events ✓ (restart Chrome after enabling)
- User logged into Reddit in Chrome
---
## Method Detection (Run First)
Chrome multi-profile can cause AppleScript to not see windows. Always detect first:
```bash
WINDOWS=$(osascript -e 'tell application "Google Chrome" to return count of windows' 2>/dev/null)
if [ "$WINDOWS" = "0" ] || [ -z "$WINDOWS" ]; then
echo "Use Method 2 (System Events + Console)"
else
echo "Use Method 1 (execute javascript)"
fi
```
---
## Method 1: AppleScript Execute JavaScript (Preferred)
Works when `count of windows > 0`.
### Navigate
```bash
osascript -e 'tell application "Google Chrome" to tell active tab of first window to set URL to "https://www.reddit.com/r/SideProject/rising/"'
```
### Execute JS & Read Result (document.title trick)
```bash
# Run JS that writes result to document.title
osascript -e 'tell application "Google Chrome" to tell active tab of first window to execute javascript "fetch(\"/api/me.json\",{credentials:\"include\"}).then(r=>r.json()).then(d=>{document.title=\"R:\"+JSON.stringify({name:d.data.name,karma:d.data.total_karma})})"'
# Wait, then read title
sleep 2
osascript -e 'tell application "Google Chrome" to return title of active tab of first window'
```
### JXA for Complex JS (avoids escaping hell)
```bash
osascript -l JavaScript -e '
var chrome = Application("Google Chrome");
var tab = chrome.windows[0].activeTab;
tab.execute({javascript: "(" + function() {
// Complex JS here — no escaping needed
fetch("/r/SideProject/rising.json?limit=10", {credentials: "include"})
.then(r => r.json())
.then(d => {
var posts = d.data.children.map(p => ({
title: p.data.title.substring(0, 60),
score: p.data.score,
comments: p.data.num_comments,
id: p.data.name,
url: "https://reddit.com" + p.data.permalink
}));
document.title = "POSTS:" + JSON.stringify(posts);
});
} + ")();"});
'
```
---
## Method 2: System Events + Console (Multi-Profile Fallback)
When AppleScript can't see Chrome windows (multi-profile bug), use keyboard automation.
### Step 1: Copy JS to Clipboard
```bash
python3 -c "
import subprocess
js = '''(async()=>{
let resp = await fetch('/api/me.json', {credentials: 'include'});
let data = await resp.json();
document.title = 'R:' + JSON.stringify({name: data.data.name, karma: data.data.total_karma});
})()'''
subprocess.run(['pbcopy'], input=js.encode(), check=True)
"
```
### Step 2: Execute via Chrome Console Keyboard Shortcuts
```bash
osascript -e '
tell application "System Events"
tell process "Google Chrome"
set frontmost to true
delay 0.3
-- Cmd+Option+J = open/close Console
key code 38 using {command down, option down}
delay 1
-- Select all + Paste + Enter
keystroke "a" using {command down}
delay 0.2
keystroke "v" using {command down}
delay 0.5
key code 36
delay 0.3
-- Close Console
key code 38 using {command down, option down}
end tell
end tell'
```
### Step 3: Read Title via System Events
```bash
sleep 3
osascript -e '
tell application "System Events"
tell process "Google Chrome"
return name of window 1
end tell
end tell'
```
---
## Workflow
### Step 1: Check Account Status
Get username, karma, verify login using `/api/me.json`.
### Step 2: Scan Rising Posts
For each target subreddit, fetch rising posts:
```
/r/{subreddit}/rising.json?limit=10
```
Look for:
- Rising posts with < 15 comments (early = more visibility)
- Score > 2 (some traction)
- Questions you can answer or discussions with genuine insight
### Step 3: Draft Comments
Rules:
- 2-4 sentences, natural tone
- Add genuine value (insights, experience, helpful info)
- No self-promotion, no links, no emojis
- Match the subreddit's culture
- Each comment must be unique
### Step 4: Post All Comments
Get modhash, then post each comment with 4s delay between posts.
```javascript
// Get modhash first
let me = await fetch("/api/me.json", {credentials: "include"}).then(r=>r.json());
let uh = me.data.modhash;
// Post comment
let body = new URLSearchParams({
thing_id: "t3_xxxxx", // post fullname
text: "Your comment here",
uh: uh,
api_type: "json"
});
let resp = await fetch("/api/comment", {
method: "POST",
credentials: "include",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
body: body.toString()
});
let result = await resp.json();
document.title = "POSTED:" + JSON.stringify(result);
```
Extract the comment ID from the response HTML: look for `id-t1_XXXXXXX` in the result.
### Step 5: Session Summary with Links
**ALWAYS end with a summary table containing direct links to every comment posted.**
The comment link format is:
```
https://www.reddit.com/r/{subreddit}/comments/{post_id}/comment/{comment_id}/
```
Where:
- `{subreddit}` = the subreddit name
- `{post_id}` = the post ID (from `thing_id` minus the `t3_` prefix)
- `{comment_id}` = extracted from the POST response (the `t1_XXXXXXX` value, minus `t1_` prefix)
**Example summary table:**
| # | Sub | Post | Comment Link |
|---|-----|------|-------------|
| 1 | r/SideProject | "Post title" | https://www.reddit.com/r/SideProject/comments/abc123/comment/xyz789/ |
| 2 | r/ClaudeAI | "Post title" | https://www.reddit.com/r/ClaudeAI/comments/def456/comment/uvw012/ |
This lets the user bookmark, follow up on replies, and track which comments got traction.
---
## Recommended Target Subreddits
| Priority | Subreddit | Why |
|----------|-----------|-----|
| High | r/SideProject | Project launches, very welcoming |
| High | r/indiehackers | Revenue/growth discussions |
| Medium | r/ClaudeAI | AI tooling audience |
| Medium | r/coolgithubprojects | Open source visibility |
| Medium | r/startups | Startup discussions |
| Medium | r/entrepreneur | Business insights |
| Medium | r/opensource | Technical audience |
---
## Comment Guidelines
- Add genuine value (insights, experience, helpful info)
- No self-promotion in comments
- Match the subreddit's tone
- Be specific, not generic
- 2-4 sentences, natural voice
---
## Rate Limiting
| Action | Limit |
|--------|-------|
| Between API calls | 2+ seconds |
| Between posts | 4+ seconds |
| Per session | Max 5 comments |
| Daily | 10-15 comments max |
---
## Karma Milestones
| Karma | Unlocks |
|-------|---------|
| 100+ | Can post in most subreddits |
| 500+ | Reduced spam filter triggers |
| 1000+ | Trusted contributor status |
| 5000+ | Community recognition |
---
## Algorithm Insights
- **First 30 minutes** determine if post reaches Hot page
- Early upvotes weighted 10x more than later ones
- 2 early comments > 20 passive upvotes
- **Best posting time**: Sunday 6-8 AM ET
- Upvote ratio matters: 100↑/10↓ (90%) beats 150↑/50↓ (75%)
---
## Troubleshooting
| Problem | Solution |
|---------|----------|
| `count of windows` = 0 | Chrome multi-profile bug → use Method 2 |
| "Allow JavaScript" not working | Restart Chrome after enabling |
| Modhash expired | Re-fetch from `/api/me.json` |
| 403 response | Rate limited, wait 5+ minutes |
| Comment not appearing | Check for shadowban: visit profile in incognito |
---
## Why AppleScript (Not Playwright/Selenium)
| Tool | Problem |
|------|---------|
| Playwright | Sets `navigator.webdriver=true`, detected instantly |
| Selenium | Same detection issue |
| Puppeteer | Same detection issue |
| curl + API | IP blocked by Reddit after few requests |
| **AppleScript** | Controls real Chrome, undetectable, cookies included |
---
## Author
**[Canlah AI](https://canlah.ai)** — Run performance marketing without breaking your brand.
- GitHub: [github.com/PHY041](https://github.com/PHY041)
- All Skills: [clawhub.ai/PHY041](https://clawhub.ai/PHY041)
don't have the plugin yet? install it then click "run inline in claude" again.