# SMIG CRM — handover doc for Keith

Hey Keith — this is everything you need to know about the system you're using. Pass this file to any dev (or feed it into Grok Build / Cursor / whatever) and they'll be able to maintain, extend, or rebuild the system.

---

## what the system does

It scans your Instagram for:
1. **DM threads that need replies** (people who messaged you, you haven't replied yet)
2. **DM threads that need follow-ups** ("bumps" — quiet conversations to re-engage)
3. **Engagers** (people who liked/commented your last 3 posts, you haven't DM'd them yet)
4. **New followers** (recently followed you, you haven't DM'd them yet)

For each person it generates a suggested message using Claude in your voice, then opens Instagram so you can paste + send manually. You stay in control of every message.

Plus: tracks all your sends to avoid double-messaging, dashboard with filters, buckets for partners/teachers/CRM/archive, mobile-friendly with deep-links to the IG app.

---

## how to access

- **Dashboard URL**: https://squeamish-sixteen-deceiving.ngrok-free.dev/network_audit.html
- **Hard refresh** after any update: cmd+shift+r on desktop, pull-to-refresh on mobile

---

## the files (where everything lives)

```
~/keith-dm-scanner/
├── server.py                 # HTTP server (port 8765, serves the dashboard)
├── build_audit.py            # Generates network_audit.html from data
├── auto_update.py            # Daily scan + rebuild (runs 01:00)
├── backup_state.py           # Daily backup of config files (runs 00:30 + 12:30)
│
├── network_audit.html        # The dashboard (rebuilt daily)
├── buckets.json              # Partner/Teacher/CRM/Archive assignments — CRITICAL
├── bump_overrides.json       # Manual bump number overrides
├── skip_list.txt             # Handles to never DM (line per handle, @-prefixed)
├── activity_log.json         # Every DM you sent (for dedup + history)
├── follow_up_FULL.csv        # DM scan results (input for build)
├── engagers.json             # Latest engagers from post scrapes
├── new_followers.json        # Latest new follower scrapes
│
├── backups/                  # Auto daily backups (14 days rolling)
│   └── 2026-05-28/
│       ├── buckets.json
│       ├── bump_overrides.json
│       ├── skip_list.txt
│       └── activity_log.json
│
└── README_FOR_KEITH.md       # This file
```

---

## launchagents (background jobs)

Located in `~/Library/LaunchAgents/`:

| name | what it does | when |
|---|---|---|
| `com.keith.dm.server` | runs server.py on port 8765 | always |
| `com.keith.dm.update` | full scan + rebuild HTML | daily 01:00 |
| `com.keith.dm.backup` | backup config files | 00:30 + 12:30 daily |
| `com.keith.dm.focus` | generates focus hints for new threads | varies |
| `com.keith.dm.engagers` | scrapes engagers from last 3 posts | varies |
| `com.keith.dm.enrich` | enriches data with extra info | varies |

**Start/stop/restart:**
```bash
launchctl unload ~/Library/LaunchAgents/com.keith.dm.server.plist
launchctl load ~/Library/LaunchAgents/com.keith.dm.server.plist
```

**Check what's running:**
```bash
launchctl list | grep keith.dm
```

---

## restoring from backup (if data gets lost)

```bash
# example: restore yesterday's buckets.json
cp ~/keith-dm-scanner/backups/2026-05-27/buckets.json ~/keith-dm-scanner/buckets.json
# then rebuild HTML
cd ~/keith-dm-scanner && python3 build_audit.py
```

Backups are kept 14 days. If you need older, check the `backups/` folder for what's available.

---

## editing config (no code knowledge needed)

### change message templates

Edit `build_audit.py` and find these lines (around line 563):

```python
t_bump    = f"{_greet}, bumping this up..."   # primary follow-up
t_circle  = f"{_greet}, how are you doing?..."  # circle back
t_sm      = f"{_greet}, hope you're doing..."   # SM (shaking medicine specific)
t_content = f"{_greet}, hope you're well..."    # content-related follow-up
t_bump3   = f"{_greet}, thought I'd try..."     # 3rd/final bump (🐉)
```

After editing, rebuild the HTML:
```bash
cd ~/keith-dm-scanner && python3 build_audit.py
```

Refresh the dashboard in your browser (cmd+shift+r).

### add to skip list (never DM these handles)

Edit `skip_list.txt`, add one handle per line, with @ prefix:
```
@some_handle
@another_handle
```

### add to do-not-contact (archive bucket)

Click 🙏 button on the row in the dashboard. It's saved to `buckets.json`.

If you need to bulk-add, edit `buckets.json` and add:
```json
"@new_handle": {
  "bucket": "EXCLUDED",
  "set_at": "2026-05-28 15:00",
  "note": "do not contact"
}
```

Restart server after manual edits:
```bash
launchctl unload ~/Library/LaunchAgents/com.keith.dm.server.plist
launchctl load ~/Library/LaunchAgents/com.keith.dm.server.plist
```

---

## tabs explained

| tab | what it shows | how rows leave |
|---|---|---|
| 💬 REPLY | people who replied to you, need response | you click suggestion → marked sent |
| ↑ BUMP UPS | quiet conversations to re-engage | you click suggestion → marked sent |
| 👋 NEW FOLLOWERS | followed you, you haven't DM'd | you click "open profile" → marked sent |
| 🎯 ENGAGERS | liked/commented your posts, you haven't DM'd | you click suggestion → marked sent |
| 🤝 PARTNERS | practitioners/collaborators (manual outreach) | bucket button changes it |
| 🌿 SM TEACHERS | shaking medicine teachers | bucket button changes it |
| 📚 CRM | already in your skool community | bucket button changes it |
| 🙏 ARCHIVE | excluded / not interested / exhausted | bucket button changes it |
| ⏸ PAUSED | recently messaged, in cooldown | system auto-manages |

### bucket buttons on each row

| icon | meaning |
|---|---|
| 🙏 | archive (no outreach) |
| 🤝 | partner / practitioner |
| 📚📚📚 | already in CRM/Skool |
| 🌿 | SM teacher |
| 📞 | call booked |
| ↩ | restore to lead |
| → bump | move from reply tab to bump tab |
| ↑ next bump | push to next bump cycle |
| ↻ reset | reset bump to previous level |

---

## filter pills

Above the table:
- **NEEDS REPLY / BUMP UP / SENT** — filter by status (only relevant on REPLY/BUMP tabs)
- **ALL** — clears status filter, default state
- **🔥 hot / ☀ warm / ⭐ score≥70** — priority filters
- **<24h / <1w / >2w / >6w / >6m** — recency filters

---

## the suggestion engine

For every row, Claude generates a suggestion based on:
1. The full DM history with that person (what you both said)
2. The "focus hint" (what they were interested in: shaking, fascia, breathwork, etc.)
3. Their recent IG posts / bio
4. Your writing style (sampled from previous DMs you sent)

When you click the suggestion → copies to clipboard → opens Instagram. You paste, edit, send.

**Voice training** (deferred — coming later): The system will track when you edit the suggestion vs accept it as-is. Over weeks, the suggestions adapt to your edits.

---

## safety pacing

In the header you see ⏱ N/h and 📅 N/day counters:
- 🟢 green: safe
- 🟡 yellow: >30/h or >100/day — pacing notice
- 🔴 red: >50/h or >200/day — slow down

If you hit red, a warning banner appears. Take a break to avoid IG flagging.

---

## common issues

### "messages aren't opening when I click"
- Hard refresh: cmd+shift+r (desktop), pull-to-refresh (mobile)
- Check ngrok tunnel is up: `curl -I https://squeamish-sixteen-deceiving.ngrok-free.dev/network_audit.html`
- Restart server (see launchagent commands above)

### "people I marked as partner/teacher/CRM are missing"
- Their bucket assignment is in `buckets.json` — never deleted unless you do it
- If rendering doesn't show them: they might not have an active DM thread anymore. Check the data:
  ```bash
  python3 -c "import json; b = json.load(open('buckets.json')); print(sum(1 for v in b.values() if v.get('bucket')=='PARTNER'), 'partners')"
  ```

### "engagers tab shows same people every day"
- The engager scrape runs on your LAST 3 POSTS. If you haven't posted recently, the engagers data is stale.
- Solution: post a new IG video/photo, and within 24h the next scan picks up new engagers.

### "the daily scan didn't run"
- Check the log: `tail -50 ~/keith-dm-scanner/auto_update.log`
- Look for "timeout" or errors
- Manually trigger: `cd ~/keith-dm-scanner && python3 auto_update.py`

### "dashboard URL changed"
- The ngrok URL `squeamish-sixteen-deceiving.ngrok-free.dev` is a persistent reserved URL
- If it ever changes (rare), check `ngrok.log` for the new URL

---

## architecture summary (for devs)

- **Stack**: Python 3.12, instagrapi (IG mobile API), Anthropic Claude API, Whisper (voice transcription), Flask-style HTTP server
- **Storage**: Plain JSON files (no DB). Daily backups in `backups/`
- **Frontend**: Single-file HTML with vanilla JS, no framework, no build step
- **Hosting**: macOS launchagents on Daichi's Mac Studio + ngrok tunnel
- **API keys needed**: Anthropic API key (Claude), IG session cookie (chrome-extracted)
- **Cost**: ~$5-15/month Anthropic API at current usage volume

### to migrate to your own server

You'd need:
1. A machine that's always on (mac, linux VPS, etc.)
2. Python 3.12 + dependencies (`pip install instagrapi anthropic flask requests`)
3. Your own Anthropic API key (anthropic.com)
4. IG session cookie (export from your logged-in chrome)
5. Optionally: ngrok account for public URL ($10/mo for reserved subdomain)

The whole `~/keith-dm-scanner/` folder is portable. Copy it, adjust paths, set env vars, install dependencies.

---

## extending the system (what's possible)

Things you can ask any dev (or Grok Build) to add:

- **Per-post engager templates** — define custom prefab message for each of your IG posts
- **Unfollow tab** — monthly suggestion of top 50 to unfollow to keep follower count clean
- **Voice learning loop** — track which suggestions you edited heavily vs accepted, claude learns
- **Multiple IG accounts** — currently single-account, can extend
- **Email/Discord notifications** — when high-priority replies come in
- **Manual scan trigger** — button to run scan now instead of waiting for daily
- **Bulk send** — review 10 suggestions at once instead of one by one
- **Lead scoring tweaks** — adjust the priority algorithm

Anyone competent with Python + JS can extend this in 1-3 days per feature.

---

## contact

Daichi built this and operates the current instance. He'll keep it running as-is but isn't doing major new features. For changes:
- Small config tweaks (templates, skip list, bucket labels): you can do yourself per above
- New features: hire a dev or use Grok Build with this README as context

Backups run twice daily. If anything ever breaks, the backups folder has your last 14 days of state. Don't panic.

---

*last updated: 2026-05-28*
