Skip to content

feat: Reddit growth agent with Slack approval workflow#3142

Merged
AhmedTMM merged 9 commits intomainfrom
feat/reddit-growth-agent
Apr 3, 2026
Merged

feat: Reddit growth agent with Slack approval workflow#3142
AhmedTMM merged 9 commits intomainfrom
feat/reddit-growth-agent

Conversation

@la14-1
Copy link
Copy Markdown
Member

@la14-1 la14-1 commented Apr 2, 2026

Summary

  • Automated Reddit scanning agent that finds threads where Spawn solves someone's problem
  • Surfaces exactly 1 best candidate per cycle to Slack (#proj-spawn) via SPA
  • Block Kit card with Approve / Edit / Skip buttons for human review
  • Approve posts the reply to Reddit via growth VM's /reply endpoint
  • Edit opens a Slack modal to modify the draft before posting
  • Tracks all candidates in SPA's SQLite database (prevents double-posting)

Architecture

Growth VM (daily cron)                    SPA VM (always-on)
────────────────────                     ─────────────────
growth.sh → Claude scans Reddit
         → extracts JSON candidate
         → POST /candidate to SPA ──────→ posts Block Kit card
                                          with Approve/Edit/Skip
                                         
                                          User clicks Approve
                                         → POST /reply to Growth VM
Growth VM receives /reply ←──────────────
         → reply.sh posts to Reddit
         → returns result ───────────────→ updates Slack message

Files

Growth VM:

  • .claude/skills/setup-agent-team/growth-prompt.md — Claude prompt (+ JSON output format)
  • .claude/skills/setup-agent-team/growth.sh — service script (+ JSON extraction + POST to SPA)
  • .claude/skills/setup-agent-team/reply.shnew: Reddit comment posting script
  • .claude/skills/setup-agent-team/trigger-server.tsmodified: added POST /reply endpoint
  • .github/workflows/growth.yml — daily trigger (2:37 PM UTC)

SPA VM:

  • .claude/skills/setup-spa/main.tsmodified: HTTP server, button handlers, edit modal
  • .claude/skills/setup-spa/helpers.tsmodified: candidates table + CRUD functions
  • .claude/skills/setup-spa/spa.test.tsmodified: candidate DB tests

Environment variables

Where Variable Purpose
Growth VM SPA_TRIGGER_URL SPA's HTTP endpoint
Growth VM SPA_TRIGGER_SECRET Auth for SPA endpoint
Growth VM REDDIT_* (4 vars) Reddit OAuth for scanning + posting
SPA VM TRIGGER_SECRET Validate growth → SPA requests
SPA VM GROWTH_TRIGGER_URL Growth VM's HTTP endpoint
SPA VM GROWTH_REPLY_SECRET Auth for growth VM /reply

Test plan

  • bash -n passes on all shell scripts
  • All 1962 tests pass (including 6 new candidate DB tests)
  • Manual trigger with test Reddit credentials
  • Verify Slack card posts with buttons
  • Click Approve → verify Reddit comment posted
  • Click Edit → modal opens → submit → modified reply posted
  • Click Skip → card updated with "Skipped by @user"
  • Double-click Approve → second click shows "already handled"

🤖 Generated with Claude Code

spawn-bot and others added 5 commits April 2, 2026 06:49
Adds an automated agent that scans Reddit for threads where Spawn
solves someone's problem, qualifies the poster, and surfaces the
best candidate to Slack for human review. Does not auto-reply.

- growth.sh: service script (same pattern as refactor.sh)
- growth-prompt.md: Claude prompt for Reddit scanning + Slack posting
- growth.yml: GitHub Actions workflow (daily trigger)
- start-growth.sh: gitignored template for VM secrets

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Simplifies the growth agent to just scan Reddit + score + qualify +
output to stdout/log. Slack (via spa) and GH issue logging will be
wired up separately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previous icon was a wrong GitHub avatar (Korean characters). Now uses
the official Pi logo (pixelated P with dot) from the project website.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Growth agent scans Reddit daily, extracts structured JSON from output,
and POSTs candidates to SPA's new HTTP endpoint. SPA posts Block Kit
cards to #proj-spawn with Approve/Edit/Skip buttons. Approve calls back
to growth VM's /reply endpoint which posts the comment to Reddit.

- growth-prompt.md: add json:candidate output format
- growth.sh: extract JSON + POST to SPA_TRIGGER_URL
- reply.sh: new script for Reddit comment posting via OAuth
- trigger-server.ts: add POST /reply endpoint
- SPA helpers.ts: add candidates table + CRUD
- SPA main.ts: HTTP server, button handlers, edit modal
- spa.test.ts: candidate DB operation tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@la14-1 la14-1 changed the title feat: Reddit growth discovery agent feat: Reddit growth agent with Slack approval workflow Apr 3, 2026
@AhmedTMM AhmedTMM marked this pull request as ready for review April 3, 2026 04:05
AhmedTMM
AhmedTMM previously approved these changes Apr 3, 2026
louisgv
louisgv previously requested changes Apr 3, 2026
Copy link
Copy Markdown
Member

@louisgv louisgv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: REQUEST_CHANGES — MEDIUM severity issues found
Commit: 9ae3f99

Findings

  • [MEDIUM] .claude/skills/setup-agent-team/growth.sh:162 — Command injection: CANDIDATE_JSON variable passed to curl -d flag without sanitization. If the agent outputs malicious JSON containing shell metacharacters, they will be expanded. Use curl --data-binary @- with heredoc or temp file instead.
  • [MEDIUM] .claude/skills/setup-agent-team/growth.sh:93-96 — Credential exposure: Reddit credentials written to temp file /tmp/growth-prompt-XXXXXX.md with world-readable permissions. Use mktemp --mode=0600 or chmod 0600 after creation.
  • [LOW] .claude/skills/setup-agent-team/growth.sh:101 — Command substitution $(cat "${PROMPT_FILE}") expands prompt content in shell context. If prompt contains shell metacharacters, injection is possible. Use claude -p "$PROMPT_FILE" (file path) instead of $(cat ...).
  • [LOW] .claude/skills/setup-agent-team/reply.sh:31-96 — Credentials visible in process list: bun -e with inline script containing Reddit credentials appears in ps aux output. Use heredoc or temp file instead.

Tests

  • bash -n: PASS
  • bun test (packages/cli): PASS
  • bun test (.claude/skills/setup-spa): PASS (100 tests)

-- security/pr-reviewer

Comment thread .claude/skills/setup-agent-team/growth.sh Outdated
Comment thread .claude/skills/setup-agent-team/growth.sh
Comment thread .claude/skills/setup-agent-team/growth.sh Outdated
Comment thread .claude/skills/setup-agent-team/reply.sh Outdated
@louisgv louisgv added the security-review-required Security review found critical/high issues - changes required label Apr 3, 2026
- chmod 0600 temp prompt file to prevent credential exposure
- Use stdin redirect instead of $(cat) for claude -p to avoid shell expansion
- Use curl --data-binary @- heredoc instead of -d to prevent command injection
- Move reply.sh bun script to temp file so credentials stay in env vars (not visible in ps)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@louisgv louisgv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: a225ef6

Summary

All MEDIUM severity findings from the prior security review have been successfully addressed. The PR demonstrates strong security practices throughout:

Prior Findings (ALL FIXED):

  • ✅ Command injection in growth.sh:162 — Fixed by using --data-binary @- instead of -d
  • ✅ Credential exposure in temp files — Fixed with chmod 0600 immediately after mktemp
  • ✅ Command substitution injection — Fixed by using stdin redirect instead of $(cat ...)
  • ✅ Credentials visible in ps output — Fixed by writing script to temp file with restricted perms

Current Findings (LOW severity only):

  • [LOW] .claude/skills/setup-agent-team/growth.sh:102 — Uses --dangerously-skip-permissions for automated agent workflow. Acceptable since human approval happens downstream via Slack.
  • [LOW] .claude/skills/setup-spa/main.ts:1280 — User-controlled number interpolated into Slack message. Safe because valibot validates it as a number and Slack Block Kit escapes content.

Strong Security Patterns Observed:

  • Timing-safe authentication using timingSafeEqual()
  • Valibot schema validation for all JSON inputs
  • Reddit post ID format validation with regex
  • Path traversal prevention via allowlist
  • Parameterized SQL queries throughout
  • URL encoding for all external API parameters
  • Secrets passed via env vars, not CLI args
  • Temp files created with mode 0600

Tests

  • bash -n (shell scripts): PASS
  • bun test (packages/cli): PASS (2002 tests)
  • bun test (setup-spa): PASS (100 tests)
  • macOS bash 3.x compatibility: PASS
  • curl|bash safety: N/A (not applicable to this feature)

-- security/pr-reviewer

Comment thread .claude/skills/setup-agent-team/growth.sh
Comment thread .claude/skills/setup-spa/main.ts
@louisgv louisgv added the security-approved Security review approved label Apr 3, 2026
@louisgv louisgv dismissed their stale review April 3, 2026 05:18

All findings have been addressed in subsequent commits (a225ef6). Approving the updated PR.

@AhmedTMM AhmedTMM merged commit 493cd1c into main Apr 3, 2026
5 checks passed
@AhmedTMM AhmedTMM deleted the feat/reddit-growth-agent branch April 3, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

security-approved Security review approved security-review-required Security review found critical/high issues - changes required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants