---
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)
