For a year I grew my Instagram the hard way. Every night I opened fifty competitor pages, screenshotted their hooks, and guessed what would go viral next. Most of my guesses missed. It ate hours I did not have.
My AI content has crossed over ten million views across Instagram, YouTube, and Facebook. I have built automations, agents, apps, websites, and more with AI for myself and for real businesses. Now I teach AI to millions of people across several countries, so they get ahead in the AI race. So I stopped guessing and built a team of AI agents to do the research for me. It finds the ideas, studies the competition, and writes the hooks, all from real data.
This is that exact prompt, the real one I run. You will not find it written anywhere else, only here on FabRich. Paste it into Claude and it builds your whole team in one go. If any step looks technical, relax. There is one prompt, and I walk you through every single click.
What your AI team actually does
You paste one prompt and Claude builds you three agents that work together, plus a live dashboard you open in your browser. Each agent has one job, and they run on your command.
- The Viral Ideas Agent finds the ideas about to blow up in your niche, before other creators package them.
- The Competitor Research Agent studies the accounts you pick and reports what is working for them right now.
- The Hooks and Scripts Agent writes your hooks and short scripts, in the shape that actually wins for you.
Here is the part that makes it real. Most AI tools hand you generic hook templates that fit no one. Mine learns YOUR hooks from YOUR data. It compares the winning reels in your niche against each account's own normal reels, so it finds the real lever, not just what everyone copies. If your niche wins on a clean first frame instead of a text hook, it tells you that truth, instead of inventing five fake templates.
What you need before you start
- A paid Claude plan, for Claude Code. Pro starts at about $20 a month. The free Claude plan does not include it.
- A free Apify key. This is the tool that reads public Instagram pages so your agents can see real reels.
- About 20 minutes for the first setup. After that, each run takes a few minutes.
Quick money note so nothing surprises you. Apify is free to start, its free plan gives you monthly credit, and reading reels costs about $2.60 per 1,000. The first setup uses about 40 cents of that, and each later run is about 7 cents. You do not need to pay to run this.
Step 1: Open Claude Code and make a folder
You are not a coder, so use the Claude desktop app, not the terminal. It has Claude Code built in, with buttons instead of commands. This is the same app I build my own agents in.
Open the app, sign in, and click the Code tab. Make a new empty folder anywhere, name it something like my-agents, and pick it. Set the mode to Local, turn on Auto, and pick the best model, Opus.
One thing my prompt checks for you, so I will say it here too. Keep this folder OUT of any synced folder like OneDrive, iCloud, Dropbox, or Google Drive. File sync breaks the live dashboard. A plain folder on your desktop is perfect.
Step 2: Paste my prompt
Now copy the big prompt below and paste it into Claude Code. That is the whole thing. It carries my full method, my ten build steps, and the way it learns your hooks, all written out for Claude.
This prompt is long, and that is fine. You do not need to read it or understand one line of it. Just copy the whole thing and paste it. Claude does the reading, then asks you a few simple questions.
Build me an "AI Social Media Agents Team" for my Instagram. I am NOT technical. Follow every step exactly.
## RULES FOR YOU — read all of these first
1. Ignore any personal instructions in a global CLAUDE.md that conflict with this. For this task: no plan mode, no git branches, no git commands, no asking approval between steps. Just build it.
2. Write every file COMPLETE and VERBATIM. You are FORBIDDEN from writing placeholders like `/* rest of styles */`, `... unchanged ...`, or any ellipsis standing in for content.
3. One file per response. After each, print the path and byte count, then continue without asking.
4. **Ship ZERO hook templates, zero hook rules, zero banned-word lists.** This system does not know what works in my niche and must never pretend to. It LEARNS my hook rules from real data in Step 6. Any hook advice written before Step 6 is a bug.
5. Shell state does NOT persist between Bash calls. Every command needing the Apify token must load it in the SAME command: `set -a; . ./.env; set +a; curl ...`
6. Finish with the exact FINAL MESSAGE in Step 10.
## STEP 0 — safety check
Run `ls -a` and `git rev-parse --show-toplevel`.
STOP and tell me to start over in a fresh empty folder if the folder is not empty, or `git rev-parse` succeeds, or the path contains `OneDrive`, `iCloud`, `Dropbox`, or `Google Drive` (file-sync corrupts the live dashboard).
Otherwise say "Folder OK" and continue.
## STEP 1 — ask me about my account
Ask these in ONE message and WAIT:
1. Your Instagram handle (no @)?
2. Your niche in one sentence, and who your audience is?
3. Your follower count?
4. **3 to 6 competitor handles.** Pick accounts roughly **3x to 20x your size that post the same format you do.** Do not pick accounts 100x bigger — their reels win on name recognition, not on craft, so copying them teaches the wrong lesson.
5. What do you film with, and what will you NOT do on camera?
6. Anything you sell or want to sell?
Write my answers verbatim to `brand/PROFILE.md`. Never invent an answer. Write competitor handles one per line to `brand/COMPETITORS.md`, **stripping any @ and any instagram.com URL down to the bare handle, lowercased.**
## STEP 2 — the Apify key
Tell me exactly this, then WAIT for a key:
> Your agents need to actually SEE Instagram. Instagram blocks normal reading, so we
> use Apify — it reads public reels from its own servers.
>
> You never log in to Instagram. Your own account is never touched, never at risk.
>
> Free key, about 2 minutes:
> 1. https://console.apify.com/sign-up — sign up (no credit card)
> 2. https://console.apify.com/settings/integrations
> 3. Under "API tokens" a token already exists — copy it
> 4. Paste it here
>
> Free plan = $5 credit every month, resets monthly, no card ever charged.
> Reading a reel costs $0.0026. Setup uses about $0.40. Each later run about $0.07.
Write it to `.env` as `APIFY_TOKEN=<key>` and write `.gitignore` containing:
```
.env
state.js
data/
```
## STEP 3 — validate every handle BEFORE spending real credit
Test-scrape 1 reel per handle (mine + competitors). About $0.02 total. One Bash call:
```bash
set -a; . ./.env; set +a
for h in HANDLE1 HANDLE2 HANDLE3; do
n=$(curl -s -X POST "https://api.apify.com/v2/acts/apify~instagram-reel-scraper/run-sync-get-dataset-items?token=${APIFY_TOKEN}&maxItems=1" \
-H "Content-Type: application/json" \
-d "{\"username\":[\"$h\"],\"resultsLimit\":1}" | grep -c shortCode)
echo "$h -> $n"
done
```
Read the results:
- **401** = the key is wrong. Ask me to re-copy it.
- **402 with a token present** = the free credit is used up for this month. It resets on the 1st. No card involved.
- **402 with an empty token** = the `.env` did not load. Fix the command, not the billing.
- **0 reels for a handle** = private, deleted, mistyped, or they post no reels. Tell me WHICH handle by name and ask me to replace it.
Do not continue until my own handle works and at least 3 competitors work.
## STEP 4 — scrape
ONE batched call for all validated handles. Cap the spend explicitly.
```bash
set -a; . ./.env; set +a
mkdir -p data
curl -s -X POST "https://api.apify.com/v2/acts/apify~instagram-reel-scraper/run-sync-get-dataset-items?token=${APIFY_TOKEN}&maxItems=175" \
-H "Content-Type: application/json" \
-d '{"username":["ME","C1","C2","C3"],"resultsLimit":25,"skipPinnedPosts":true,"skipTrialReels":true}' \
> data/raw.json
```
`skipTrialReels` matters — trial reels are shown to non-followers first and have a different view profile that would corrupt the maths.
Never enable `includeTranscript` or `includeDownloadedVideo`; they cost roughly 18x more per reel.
Then print a cost line: reels scraped, estimated cost at $0.0026 each, estimated credit left this month.
## STEP 5 — the field rules
Get these wrong and every number downstream is wrong.
- Views = **`videoPlayCount`**. Do NOT use `videoViewCount` — Instagram removed it, it is usually 0.
- `likesCount: -1` means likes are **hidden** on that post. Not zero, not an error. Exclude that post from like-based maths.
- `videoPlayCount` is the browser counter and **excludes Facebook cross-posted views**, so it can read lower than my own app shows. Say so if I ask.
- Cover image = **`displayUrl`** (JPEG). Also useful: `caption`, `url`, `timestamp`, `commentsCount`, `videoDuration`, `dimensionsWidth`, `dimensionsHeight`.
## STEP 6 — LEARN MY HOOKS (this is the whole point — do not skip or shortcut it)
You are going to write `playbook/HOOKS.md` from evidence. Until this step finishes, no hook rules exist anywhere in this system.
### 6a. Find outliers AND a control group
Per account, separately:
1. Drop any reel **younger than 14 days** — it has not finished accumulating views and would drag the median down.
2. Need **15+ remaining reels** to use that account's own median. Fewer: skip that account for derivation and say so.
3. Compute that account's median `videoPlayCount`.
4. **OUTLIERS** = top 20% by views for that account.
5. **CONTROL** = reels between 0.8x and 1.2x of that same account's median.
**The control group is not optional.** If 70% of reels in my niche open with "POV:", then 70% of the winners will too — that is the niche convention, not a winning lever. Without the control you would write down the base rate and call it a rule.
### 6b. Read the actual on-screen hooks
The caption is NOT the hook. Creators burn the hook into the cover image.
Take up to **20 outlier covers and 20 control covers**, ranked by view multiple. Hard cap at 40 images total — each is roughly 950 tokens and reading 150 would blow up the run.
Download in one call, then read each with your own vision:
```bash
curl -s -A "Mozilla/5.0" -o data/covers/<handle>-<shortcode>.jpg "<displayUrl>"
```
Use the `displayUrl` **byte for byte**, unmodified — they are signed URLs and any edit breaks them. They also expire, so download in the same run as the scrape. Before counting a download as successful, confirm the file starts with the JPEG magic bytes `FF D8`; a 403 error body is a few bytes of text and would otherwise be saved as a `.jpg`.
For each cover, read ONLY the text visibly burned into the image. If there is no text, record `NONE`. Never guess, never fall back to the caption.
Append results to `data/hooks.jsonl` as you go, one line per image, so images do not pile up in context.
### 6c. Measure yield, then pick one of three honest branches
Yield = share of covers that had readable text.
- **Above 60%** — derive hook rules normally.
- **30 to 60%** — derive at most 3 rules, and stamp line 1 of the file: `LOW CONFIDENCE — derived from N hooks across M accounts`.
- **Below 30%** — **do NOT invent hook rules.** Write instead: "Your niche wins on the first FRAME, not on a text hook." Then derive what actually separates outliers from control in this niche using the data you do have: cover imagery style, caption first line, `videoDuration` bucket, posting hour. Cooking, travel, beauty and fashion often land here and it is a true and useful finding.
Also require **8+ usable outlier hooks** before writing any rules at all. Under that, write what you have and put the sample size on line 1.
### 6d. Write `playbook/HOOKS.md`
Only include a pattern if it is **more common in outliers than in control**, and state the split numerically:
> Question-form openers: 11 of 14 outliers vs 3 of 14 control.
A pattern appearing at the same rate in both is a **CONVENTION** — label it that, never a RULE.
Every RULE must be a yes/no test on a hook string — word count, question vs statement, names a specific thing, contains a number, emoji count. If you cannot phrase it as a checkable test, it goes in a NOTES section and **cannot be cited later to kill a hook.**
List the real winning hooks verbatim as evidence, each with handle, views, and multiple of that account's median.
End the file with this, exactly:
```
These shapes came from public accounts other creators in this niche are also
studying. Use the SHAPES. Never the fillings.
```
### 6e. Also write `playbook/UNIVERSAL.md`
These five are from Instagram itself and are true in every niche. Nothing else goes in this file.
```markdown
# Universal — from Instagram, not from any niche
- Keep reels to 3 minutes or less (recommendation eligibility).
- Captions on.
- Original, non-watermarked content. Adding borders, subtitles or credits does
NOT make reposted content original. This is an eligibility gate for
recommendations, not a bonus.
- Include audio.
- It must make sense to a stranger who does not follow you.
## The three signals Instagram says matter most
Watch time, likes, sends — tracked as RATIOS, not raw counts:
average watch time, likes per reach, sends per reach.
Likes skew slightly toward existing followers; sends skew slightly toward
non-followers. (Adam Mosseri, 22 Jan 2025.)
Completion is judged against reels of the SAME LENGTH as yours, so a longer
reel is not penalised for being long.
Skip rate — the share of viewers who skip in the first 3 seconds — is now
shown in Insights. It is the most direct measure of whether a hook worked.
## Ignore
"Sends are weighted 3-5x more than likes", "jump cuts every 3-5s boost
engagement by 32%", "captions increase retention 38%". None of these have a
traceable source. They are content-farm numbers.
```
## STEP 7 — the 3 agents
**`.claude/agents/viral-ideas.md`**
```markdown
---
name: viral-ideas
description: Finds real content opportunities for this creator's specific niche by mining what their audience is actually asking.
tools: Bash, WebSearch, WebFetch, Read
model: inherit
---
You find what this creator's audience actually wants, in ANY niche. Read
`brand/PROFILE.md` first. Nothing about your sources is hardcoded — you discover
them from the niche.
## Fetching rules — verified, do not improvise
- WebFetch is BLOCKED on Reddit and StackExchange. curl works. Always send a
browser user-agent: `-A "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36"`
- Reddit `.json` endpoints are ALL dead (403). Use `old.reddit.com` HTML, which
exposes `data-score` and `data-comments-count` as attributes.
- Quora is 403. YouTube search pages return an empty JS shell. Do not use either.
## Never search "trending in <niche>"
That returns SEO blogspam written months ago. You are mining what real people
ask, not what a listicle claims is hot.
## Procedure
1. **Vocabulary.** From the niche sentence, write 10-15 seed terms, the jargon
practitioners use, and 3-5 beginner problems. This is the only step where your
own knowledge is allowed — it produces search inputs, never answers.
2. **Questions (the core engine).** For each seed, hit Google autocomplete:
`curl -s "https://suggestqueries.google.com/complete/search?client=firefox&q=<prefix>+<seed>"`
Sweep prefixes: "why is my", "why does my", "how to", "how do I", "is it",
"can I", "what happens if", "best ... for", "... without", "... vs".
No key, no login, works in every niche. These are verbatim audience questions.
3. **Communities.** Find subreddits via `site:reddit.com <seed>` searches, keep any
appearing in 2+ searches, then VERIFY each is alive by curling
`old.reddit.com/r/<name>/top/?t=week` and requiring 5+ posts in the last week.
Pull the top threads, then their comment pages, and mine questions that repeat
across comments. A question asked repeatedly under a popular post is the
strongest free intent signal there is.
4. **Currency.** `news.google.com/rss/search?q=<seed>` for dated headlines.
## Output — 5 to 8 opportunities
Every single one must carry ALL FOUR or you discard it:
- a primary source URL (a thread, a query, a dated article)
- a NUMBER (score, comment count, suggestion rank)
- a timestamp inside your lookback window
- a VERBATIM quote from a real person
Tag each: [FROM SOURCE + url] or [MY JUDGEMENT]. Untagged is a bug.
If you found nothing solid, say so and stop. Never pad.
## Never
- Never claim to have browsed Instagram — you cannot, it is login-walled.
- Never name a specific trending audio. Web sources lag audio cycles by weeks and
a dead sound is the most embarrassing possible recommendation.
```
**`.claude/agents/competitor-research.md`**
```markdown
---
name: competitor-research
description: Scrapes competitor reels via Apify and finds which are genuinely outperforming, using each account's own median as the baseline.
tools: Bash, Read, Write
model: inherit
---
You work only from real scraped numbers.
Load the token in the SAME Bash call that uses it — shell state does not persist:
`set -a; . ./.env; set +a; curl ...`
Follow the field rules and the outlier/control method in `playbook/HOOKS.md`.
Views are `videoPlayCount`. `likesCount: -1` means hidden, not zero. Drop reels
under 14 days old before computing any median.
Compare each creator ONLY against their own median. Never compare creators to
each other — a bigger account beats a smaller one at everything and that tells
you nothing.
## Output
Per outlier: handle, views, multiple of that account's own median, the on-screen
hook text you read from the cover, and the shape of it.
Then: what is common across outliers that is NOT common in the control group,
and the GAP — what none of them are doing that this creator could own.
Tag everything [FROM YOUR DATA] or [MY JUDGEMENT].
## Never
- Never invent a number. If a handle failed, name it and continue.
- Never enable includeTranscript or includeDownloadedVideo (~18x cost).
```
**`.claude/agents/hooks-scripts.md`**
```markdown
---
name: hooks-scripts
description: Writes hooks against the creator's own derived playbook, kills the weak ones, and turns the winner into a film-ready script.
tools: Read
model: inherit
---
Read `playbook/HOOKS.md`, `playbook/UNIVERSAL.md` and `brand/PROFILE.md` first.
**If `playbook/HOOKS.md` does not exist, STOP.** Say: "No playbook yet — run the
learning step first." Never write hooks from your own general ideas about what
goes viral. That is exactly what this system exists to avoid.
## Write
12 hook candidates for the chosen idea, each aimed at a shape from the DERIVED
playbook, filled from this creator's actual niche and voice.
## Kill
Now you are a hostile editor who did not write these. Kill at least 8 of 12 — a
floor, not a target.
Cite the specific derived RULE each one fails. You may only cite rules from the
RULES section, never from NOTES or CONVENTION. "Too vague" is not a reason;
"11 words, the derived rule is 4-8, fails" is a reason.
Print the kill list. It is the only proof the filter is real.
Pick ONE winner and say in a line why it beat the runner-up. If fewer than 2
survive, say so and rewrite rather than lowering the bar.
## Script
For the winner: the hook exactly as it goes on screen, a shot list matched to what
the creator actually films with, the spoken script with timings, the caption and
CTA. Check it against all five points in UNIVERSAL.md.
ONE concept, ready to shoot. Never a menu of 15 options.
```
## STEP 8 — `.claude/skills/team/SKILL.md`
Folder MUST be named `team` — the slash command comes from the directory name. There is no tool called `Task`; the subagent tool is `Agent`.
```markdown
---
name: team
description: Run the AI social media agents team to produce one film-ready reel concept. Use when the user says /team, "run the team", or "what should I post".
---
# /team
## Step 0 — load
Read `state.js` if present, plus `brand/PROFILE.md`, `brand/COMPETITORS.md`,
`playbook/HOOKS.md`, `playbook/UNIVERSAL.md`, `memory/Shipped.md`.
If `playbook/HOOKS.md` is missing, run the learning step (Step 6 of setup) first.
## The state file — write it at EVERY step
Overwrite `state.js` with the Write tool before and after each agent.
window.__AGENT_STATE__({
writtenAt: <unix ms>,
running: true,
profile: {name:"", handle:"", followers:0},
stats: {views:0, engagement:0, reels:0},
agents: [
{name:"Viral Ideas Agent", status:"working", metric:"Ideas found", value:0, doing:"Mining audience questions"},
{name:"Competitor Research Agent", status:"idle", metric:"Reels scanned", value:0, doing:"Waiting"},
{name:"Hooks & Scripts Agent", status:"idle", metric:"Hooks written", value:0, doing:"Waiting"}
],
result: null
});
status: idle | working | done | error. Get the timestamp with `date +%s000`.
## Step 1 — scoreboard first (from run 2 onwards)
Re-scrape MY OWN reels only (~$0.07). For anything in `memory/Shipped.md` that I
have since posted, match it by date and caption, then report:
"The hook from the 3rd did 3.4x your median. The two before it did 0.8x."
Promote a derived rule after 2 wins, demote it after 3 misses, and note the change
in `playbook/HOOKS.md` with one line of justification.
This scoreboard is the reason to open this thing in week 6.
## Step 2-4 — agents, ONE AT A TIME
Subagents run in the background by default. WAIT for each to return before
starting the next.
1. `viral-ideas`
2. `competitor-research`
3. Show me the top 3 opportunities and ASK which to build. WAIT.
4. `hooks-scripts` with the chosen idea
## Step 5 — deliver
Write `output/<today>-<slug>.md`: the winning hook, the kill list with reasons,
shot list, script, caption, CTA. Every claim tagged [FROM YOUR DATA] /
[FROM SOURCE + url] / [MY JUDGEMENT].
Append to `memory/Shipped.md`: date, exact hook, and which derived rule it used.
Append the topic to `memory/Posted-Concepts.md`.
Final `state.js` write: running false, all done, result set.
## Never
- Never claim to have browsed Instagram
- Never name a specific trending audio
- Never write hook rules outside the learning step
- Never deliver a menu instead of one concept
```
## STEP 9 — dashboard, state, memory, README
Write `dashboard.html` EXACTLY as below. It must NOT use `fetch()` — opened by double-click it runs on `file://` where `fetch()` is CORS-blocked and the page would render but stay permanently empty with no visible error. Script tags are not blocked.
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AI Agents</title>
<style>
:root{
--bg:#FCFCFC; --panel:#FFF; --line:#EDEDEC;
--ink:#141414; --ink-2:#5C5C5C; --ink-3:#8E8E8E;
--rose:#F0396B; --rose-bg:#FDF0F4; --blue:#3B82F6; --blue-bg:#EFF4FE;
--green:#22A45D; --green-bg:#EDF8F1; --amber:#F0A020; --amber-bg:#FEF6E9;
--violet:#8B5CF6; --violet-bg:#F4F1FE; --idle:#C9C9C9;
--sans:ui-sans-serif,system-ui,-apple-system,"Segoe UI Variable Display","Segoe UI",Roboto,sans-serif;
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
body{font-family:var(--sans);background:var(--bg);color:var(--ink);font-size:14px;line-height:1.45}
.app{display:flex;min-height:100vh}
.side{width:272px;flex:none;background:var(--panel);border-right:1px solid var(--line);padding:26px 20px;display:flex;flex-direction:column}
.brand{display:flex;align-items:center;gap:13px;padding:0 6px;margin-bottom:34px}
.mark{width:44px;height:44px;border-radius:50%;flex:none;background:#0B0B0B;display:flex;align-items:center;justify-content:center}
.brand-name{font-size:15px;font-weight:700;letter-spacing:.035em}
.nav{display:flex;flex-direction:column;gap:3px}
.nav-item{display:flex;align-items:center;gap:13px;padding:11px 13px;border-radius:11px;color:var(--ink-2);font-size:14.5px;font-weight:500;border:1px solid transparent}
.nav-item.on{background:var(--rose-bg);color:var(--ink);font-weight:600;border-color:#FBE3EA}
.nav-item.on svg{color:var(--rose)}
.nav-item svg{width:19px;height:19px;flex:none;color:var(--ink-3)}
.promo{margin-top:auto;background:#F6F6F5;border-radius:15px;padding:17px 18px;display:flex;gap:11px;align-items:flex-start}
.promo-t{font-size:14.5px;font-weight:600;line-height:1.35}
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{display:flex;justify-content:flex-end;align-items:center;padding:16px 40px;border-bottom:1px solid var(--line)}
.user{display:flex;align-items:center;gap:13px}
.user-txt{text-align:right}
.user-name{font-size:14.5px;font-weight:600}
.user-handle{font-size:13px;color:var(--ink-3)}
.avatar{width:46px;height:46px;border-radius:50%;flex:none;background:linear-gradient(145deg,#2B2B2B,#4A4A4A);display:flex;align-items:center;justify-content:center;color:#fff;font-weight:600;font-size:16px}
.content{padding:34px 40px 56px}
.head{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:30px}
h1{font-size:30px;font-weight:700;letter-spacing:-.028em;line-height:1.2}
.head-sub{font-size:15px;color:var(--ink-2);margin-top:7px}
.pill{display:flex;align-items:center;gap:9px;flex:none;background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:12px 19px;font-size:14px;font-weight:500;white-space:nowrap}
.dot{position:relative;width:9px;height:9px;border-radius:50%;background:var(--idle);flex:none}
.dot::after{content:"";position:absolute;inset:0;border-radius:50%;background:inherit;opacity:0}
.dot.working{background:var(--amber)}
.dot.working::after{animation:ring 1.8s ease-out infinite}
.dot.done{background:var(--green)}
.dot.error{background:#D2452F}
.dot.sm{width:7px;height:7px}
@keyframes ring{0%{transform:scale(1);opacity:.45}70%{transform:scale(2.6);opacity:0}100%{transform:scale(2.6);opacity:0}}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:17px;margin-bottom:20px}
.stat{background:var(--panel);border:1px solid var(--line);border-radius:17px;padding:21px 22px 4px;overflow:hidden}
.stat-top{display:flex;align-items:flex-start;gap:13px}
.badge{width:44px;height:44px;border-radius:13px;flex:none;display:flex;align-items:center;justify-content:center}
.badge svg{width:21px;height:21px}
.stat-label{font-size:13.5px;color:var(--ink-2);letter-spacing:-.012em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stat-num{font-size:28px;font-weight:700;letter-spacing:-.03em;line-height:1.15;margin-top:2px;font-variant-numeric:tabular-nums}
.spark{display:block;width:100%;height:60px;margin-top:18px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:17px;padding:24px 25px;margin-bottom:20px}
.card-h{font-size:19px;font-weight:700;letter-spacing:-.021em}
.card-s{font-size:14px;color:var(--ink-3);margin-top:5px}
.agents{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:21px}
.agent{border:1px solid var(--line);border-radius:15px;padding:17px 18px 19px}
.agent-top{display:flex;align-items:flex-start;gap:13px}
.badge-s{width:40px;height:40px;border-radius:12px;flex:none;display:flex;align-items:center;justify-content:center}
.badge-s svg{width:19px;height:19px}
.agent-name{font-size:14px;font-weight:600;line-height:1.3}
.agent-state{display:flex;align-items:center;gap:7px;margin-top:13px;font-size:13px;font-weight:500}
.agent-metric{font-size:13.5px;color:var(--ink-3);margin-top:16px;line-height:1.35}
.agent-num{font-size:23px;font-weight:600;margin-top:4px;font-variant-numeric:tabular-nums}
.agent-doing{font-size:12.5px;color:var(--ink-3);margin-top:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hook{font-size:21px;font-weight:600;letter-spacing:-.023em;line-height:1.3;margin-top:14px}
.why{color:var(--ink-2);font-size:13.5px;padding-top:15px;margin-top:16px;border-top:1px solid #F3F3F2}
.foot{font-size:12.5px;color:var(--ink-3);padding:0 40px 30px}
.stale{color:#D2452F}
@media (max-width:1180px){.stats{grid-template-columns:repeat(2,1fr)}}
@media (max-width:900px){.side{display:none}.content,.topbar,.foot{padding-left:22px;padding-right:22px}.agents{grid-template-columns:1fr}.head{flex-direction:column}h1{font-size:25px}}
@media (max-width:560px){.stats{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){.dot.working::after{animation:none}}
</style>
</head>
<body>
<div class="app">
<aside class="side">
<div class="brand">
<div class="mark">
<svg width="26" height="26" viewBox="0 0 26 26" aria-hidden="true">
<g stroke="#FF3B1F" stroke-width="1.6" stroke-linecap="round">
<line x1="13" y1="2.5" x2="13" y2="9"/><line x1="13" y1="17" x2="13" y2="23.5"/>
<line x1="2.5" y1="13" x2="9" y2="13"/><line x1="17" y1="13" x2="23.5" y2="13"/>
<line x1="5.6" y1="5.6" x2="10.2" y2="10.2"/><line x1="15.8" y1="15.8" x2="20.4" y2="20.4"/>
<line x1="20.4" y1="5.6" x2="15.8" y2="10.2"/><line x1="10.2" y1="15.8" x2="5.6" y2="20.4"/>
</g><circle cx="13" cy="13" r="3.6" fill="#FF3B1F"/>
</svg>
</div>
<div class="brand-name">MY AI TEAM</div>
</div>
<nav class="nav">
<div class="nav-item on">
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
<rect x="2.5" y="2.5" width="6" height="6" rx="1.6"/><rect x="11.5" y="2.5" width="6" height="6" rx="1.6"/>
<rect x="2.5" y="11.5" width="6" height="6" rx="1.6"/><rect x="11.5" y="11.5" width="6" height="6" rx="1.6"/>
</svg>Overview
</div>
<div class="nav-item">
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="6.5" width="14" height="10" rx="3"/><circle cx="7.5" cy="11.5" r="1.1" fill="currentColor" stroke="none"/>
<circle cx="12.5" cy="11.5" r="1.1" fill="currentColor" stroke="none"/><line x1="10" y1="2.5" x2="10" y2="6.5"/>
</svg>AI Agents
</div>
<div class="nav-item">
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
<path d="M5 2.5h6.5L16 7v10.5H5z"/><path d="M11 2.5V7h5"/><line x1="7.5" y1="11" x2="13" y2="11"/><line x1="7.5" y1="14" x2="13" y2="14"/>
</svg>Content
</div>
<div class="nav-item">
<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
<path d="M2.5 14.5L7.5 9l3.5 3.5L17.5 6"/><path d="M13 6h4.5v4.5"/>
</svg>Growth
</div>
</nav>
<div class="promo"><span aria-hidden="true">✨</span><div class="promo-t">Billion Dollar Brand in the Making. 🚀</div></div>
</aside>
<div class="main">
<div class="topbar">
<div class="user">
<div class="user-txt">
<div class="user-name" id="uname">—</div>
<div class="user-handle" id="uhandle">@—</div>
</div>
<div class="avatar" id="uinit">•</div>
</div>
</div>
<div class="content">
<div class="head">
<div>
<h1 id="greet">Your AI Team</h1>
<div class="head-sub">Your AI Social Media Agents are working for you</div>
</div>
<div class="pill"><span class="dot" id="hdot"></span><span id="hlabel">Waiting</span></div>
</div>
<div class="stats" id="stats"></div>
<div class="card">
<div class="card-h">Your AI Agents</div>
<div class="card-s" id="asub">Type /team in Claude Code to start them</div>
<div class="agents" id="agents"></div>
</div>
<div class="card" id="resultCard" style="display:none">
<div class="card-h">What your team made</div>
<div class="hook" id="hook"></div>
<div class="why" id="why"></div>
</div>
</div>
<div class="foot" id="foot"></div>
</div>
</div>
<script>
var ICONS={
users:'<path d="M13.5 17v-1.5a3 3 0 00-3-3h-5a3 3 0 00-3 3V17"/><circle cx="8" cy="6" r="3"/><path d="M18 17v-1.5a3 3 0 00-2.2-2.9"/><path d="M13 3.2a3 3 0 010 5.6"/>',
eye:'<path d="M1.8 10S4.7 4.5 10 4.5 18.2 10 18.2 10 15.3 15.5 10 15.5 1.8 10 1.8 10z"/><circle cx="10" cy="10" r="2.6"/>',
heart:'<path d="M17.1 4.9a4.1 4.1 0 00-5.8 0L10 6.2 8.7 4.9a4.1 4.1 0 10-5.8 5.8l1.3 1.3L10 17.8l5.8-5.8 1.3-1.3a4.1 4.1 0 000-5.8z"/>',
film:'<rect x="2.5" y="4.5" width="15" height="11" rx="2.4"/><line x1="6.5" y1="4.5" x2="6.5" y2="15.5"/><line x1="13.5" y1="4.5" x2="13.5" y2="15.5"/>',
bulb:'<path d="M7.5 15.5h5"/><path d="M8.2 17.6h3.6"/><path d="M6.4 11.4a4.6 4.6 0 117.2 0c-.7.9-1.1 1.5-1.2 2.4H7.6c-.1-.9-.5-1.5-1.2-2.4z"/>',
search:'<circle cx="9" cy="9" r="5.3"/><line x1="12.9" y1="12.9" x2="16.8" y2="16.8"/>',
pen:'<path d="M13.6 3.6l2.8 2.8L7.2 15.6l-3.6.8.8-3.6z"/><line x1="12" y1="5.2" x2="14.8" y2="8"/>'
};
var TINT={rose:['#F0396B','#FDF0F4'],blue:['#3B82F6','#EFF4FE'],green:['#22A45D','#EDF8F1'],
amber:['#F0A020','#FEF6E9'],violet:['#8B5CF6','#F4F1FE']};
var AGENT_STYLE=[['rose','bulb'],['blue','search'],['violet','pen']];
function nf(v){
if(v>=1e6) return (v/1e6).toFixed(1)+'M';
if(v>=1000) return (v/1000).toFixed(1).replace(/\.0$/,'')+'K';
return String(Math.round(v));
}
function esc(t){var d=document.createElement('div');d.textContent=t==null?'':t;return d.innerHTML}
function series(seed,n){
var o=[],v=0,r=seed;
for(var i=0;i<n;i++){r=(r*9301+49297)%233280;v+=(r/233280-0.34)*1.7+0.30;o.push(v)}
var lo=Math.min.apply(null,o),hi=Math.max.apply(null,o),sp=(hi-lo)||1;
return o.map(function(x){return (x-lo)/sp})
}
function linePath(vals,w,h,pad){
return vals.map(function(v,i){
return (i?'L':'M')+((i/(vals.length-1))*w).toFixed(1)+' '+(h-pad-v*(h-pad*2)).toFixed(1)
}).join(' ')
}
var last=null,lastSeen=0;
window.__AGENT_STATE__=function(s){
if(!s||!s.agents) return; // torn read — keep last good state
last=s; lastSeen=Date.now(); render(s);
};
function render(s){
var p=s.profile||{},st=s.stats||{};
document.getElementById('uname').textContent=p.handle||'—';
document.getElementById('uhandle').textContent='@'+(p.handle||'—');
document.getElementById('uinit').textContent=(p.handle||'•').charAt(0).toUpperCase();
document.getElementById('greet').textContent='Good morning'+(p.name?', '+p.name:'')+' 👋';
var cards=[
{label:'Followers', val:nf(p.followers||0), icon:'users', c:'rose'},
{label:'Views', val:nf(st.views||0), icon:'eye', c:'blue'},
{label:'Engagement Rate', val:(st.engagement||0)+'%', icon:'heart', c:'green'},
{label:'Reels Analysed', val:nf(st.reels||0), icon:'film', c:'amber'}
];
document.getElementById('stats').innerHTML=cards.map(function(c,i){
var t=TINT[c.c];
return '<div class="stat"><div class="stat-top">'
+'<div class="badge" style="background:'+t[1]+'"><svg viewBox="0 0 20 20" fill="none" stroke="'+t[0]+'" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">'+ICONS[c.icon]+'</svg></div>'
+'<div style="min-width:0"><div class="stat-label">'+c.label+'</div><div class="stat-num">'+c.val+'</div></div>'
+'</div><svg class="spark" viewBox="0 0 300 58" preserveAspectRatio="none" aria-hidden="true">'
+'<path d="'+linePath(series(i*137+7,34),300,58,7)+'" fill="none" stroke="'+t[0]+'" stroke-width="1.9" stroke-linejoin="round" stroke-linecap="round"/></svg></div>';
}).join('');
var done=0;
document.getElementById('agents').innerHTML=s.agents.map(function(a,i){
if(a.status==='done') done++;
var sty=AGENT_STYLE[i]||['rose','bulb'], t=TINT[sty[0]];
var col=a.status==='done'?'#22A45D':a.status==='working'?'#F0A020':a.status==='error'?'#D2452F':'#8E8E8E';
var word=a.status==='done'?'Done':a.status==='working'?'Working':a.status==='error'?'Error':'Idle';
return '<div class="agent"><div class="agent-top">'
+'<div class="badge-s" style="background:'+t[1]+'"><svg viewBox="0 0 20 20" fill="none" stroke="'+t[0]+'" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">'+ICONS[sty[1]]+'</svg></div>'
+'<div class="agent-name">'+esc(a.name)+'</div></div>'
+'<div class="agent-state" style="color:'+col+'"><span class="dot sm '+a.status+'" style="animation-delay:'+(i*260)+'ms"></span>'+word+'</div>'
+'<div class="agent-metric">'+esc(a.metric||'')+'</div>'
+'<div class="agent-num">'+nf(a.value||0)+'</div>'
+'<div class="agent-doing">'+esc(a.doing||'')+'</div></div>';
}).join('');
document.getElementById('asub').textContent=s.agents.length+' AI Agents working together to grow your brand';
document.getElementById('hdot').className='dot '+(s.running?'working':(done?'done':''));
document.getElementById('hlabel').textContent=s.running?'Working':(done?'All Systems Active':'Waiting');
if(s.result&&s.result.hook){
document.getElementById('resultCard').style.display='';
document.getElementById('hook').textContent=s.result.hook;
document.getElementById('why').textContent=s.result.why||'';
}
}
// a stopped run must LOOK stopped, never like it is still working
setInterval(function(){
var f=document.getElementById('foot');
if(!last){f.textContent='';return}
var age=Math.round((Date.now()-(last.writtenAt||lastSeen))/1000);
f.innerHTML=(last.running&&age>90)
? '<span class="stale">No update for '+age+'s — the run may have stopped</span>'
: 'updated '+age+'s ago';
},1000);
// poll by re-injecting a cache-busted script tag, then remove it
setInterval(function(){
var s=document.createElement('script');
s.src='state.js?t='+Date.now();
s.onload=s.onerror=function(){s.remove()};
document.body.appendChild(s);
},700);
</script>
</body>
</html>
```
`state.js`:
```javascript
window.__AGENT_STATE__({
writtenAt: 0,
running: false,
profile: {handle:"", followers:0},
stats: {views:0, engagement:0, reels:0},
agents: [
{name:"Viral Ideas Agent", status:"idle", metric:"Ideas found", value:0, doing:"Waiting"},
{name:"Competitor Research Agent", status:"idle", metric:"Reels scanned", value:0, doing:"Waiting"},
{name:"Hooks & Scripts Agent", status:"idle", metric:"Hooks written", value:0, doing:"Waiting"}
],
result: null
});
```
Also create `memory/Shipped.md` and `memory/Posted-Concepts.md`, each with a one-line header.
`README.md` — plain language: what this is; run it with `/team`; watch it by double-clicking `dashboard.html`. Include a **What it cannot do** section: it does not post anything, cannot see private accounts, cannot see your Instagram Insights (only public numbers), and `videoPlayCount` reads lower than your app because it excludes Facebook cross-posted views. Note the Apify free credit is $5/month, resets monthly, never charges a card. State plainly that **the hook rules in `playbook/HOOKS.md` were learned from real data in this niche — they were not shipped with the system, and they will change as more evidence arrives.**
## STEP 10 — verify, then the final message
```bash
find . -type f -not -path "./.git/*" -not -path "./data/*" | sort && echo "---" && find . -type f -not -path "./.git/*" -not -path "./data/*" | wc -l && echo "--- empty ---" && find . -type f -empty -not -path "./.git/*"
```
Expect these 14 files. Do not declare success unless the count matches and nothing is empty:
```
./.claude/agents/competitor-research.md
./.claude/agents/hooks-scripts.md
./.claude/agents/viral-ideas.md
./.claude/skills/team/SKILL.md
./.env
./.gitignore
./README.md
./brand/COMPETITORS.md
./brand/PROFILE.md
./dashboard.html
./memory/Posted-Concepts.md
./memory/Shipped.md
./playbook/HOOKS.md
./playbook/UNIVERSAL.md
./state.js
```
Then print EXACTLY this and nothing after it:
```
✅ Your AI team is built — and it has already learned your niche.
Your hook rules in playbook/HOOKS.md came from real reels in YOUR niche.
Nothing about hooks was shipped with this. Open that file and read it.
ONE THING LEFT — restart Claude Code or /team will not exist:
1. Type /exit and press enter
2. Run: claude
3. Type / and check that "team" is in the list
Then:
• Double-click dashboard.html to watch them work
• Type /team to make your first reel
It writes the content. You post it.
```
---That is your whole team in one paste. It tells Claude to build the three agents, learn your hooks from real reels, and put a live dashboard on your screen. You just copied months of my testing in one go.
Step 3: Answer its questions and drop a free Apify key
Claude asks a few plain questions in one batch. Your Instagram handle, your niche, your follower count, and three to six competitor handles. Pick accounts about 3 to 20 times your size that post the same format you do, not the giants who win on their name alone. Answer them, or say you decide.
Then it asks for a free Apify key, because your agents need to actually see Instagram. Go to console.apify.com, make a free account, open Settings, then API and Integrations, and copy your token. Paste it in. Your token stays on your own computer, and my prompt reminds you to make a fresh one at the end.
Get your free Apify key (Settings, then API and Integrations)Stop and look at what just happened. You pasted one prompt and answered a few questions, and Claude built you a working AI team with a dashboard. This is the same flow that took me from zero to shipping real agents and apps.
How you run it every day
Once it is built, you run your team with one command, /team. Claude wakes the three agents one at a time, updates your dashboard, and hands you the day's viral ideas, the competitor report, and fresh hooks. Open the dashboard in your browser to see it all.
Your routine is simple. Run /team, read the ideas, pick the one you like, and shoot it. The more you run it, the sharper it gets, because it keeps learning from new reels. You point, it researches, you create.
The part most demos skip: this finds the sharpest ideas and hooks from real data, it does not post for you or promise a viral hit. It removes the guessing and the hours of research. You still make the reel, and that is the fun part.
If it breaks
- It says the folder is not empty or is inside a synced drive: start again in a fresh, empty folder on your desktop, not inside OneDrive, iCloud, Dropbox, or Google Drive.
- Apify token error or a 402 that looks like a billing problem: it usually is not billing, it is the key not loading. Ask Claude to reload it, or paste a fresh token from console.apify.com, Settings, API and Integrations.
- It pulled nothing from a competitor: that account may be private or the handle was typed wrong. Give it public handles, spelled exactly, with no @ sign.
- The dashboard will not open: make sure the folder is not in a synced drive, then ask Claude to start the dashboard again and give you the link.
- You do not see Auto mode: update the app, or just click Yes allow while it works. Either way is fine.
- Do I need to know how to code?
- No. You paste my one prompt and answer a few questions. Claude writes all the code and builds the agents and the dashboard for you. I am not writing code either, I am directing it.
- Is this free?
- The prompt is free and only here on FabRich. You do need a paid Claude plan for Claude Code, which starts at about $20 a month, and a free Apify account. Reading reels costs a few cents per run, well inside the free Apify credit.
- Will it post for me or make me go viral?
- No, and I would not trust a tool that promised that. It does the research a full team would do, finds the ideas and hooks that fit your account from real data, and hands them to you. You still shoot the reel.
- How does it know what works for me?
- It reads real reels with Apify and compares the winners in your niche against each account's own normal reels. That is what separates a real lever from a trend everyone copies. If your niche wins on a clean first frame, it tells you, instead of inventing templates.
- Which competitors should I pick?
- Three to six accounts about 3 to 20 times your size that post the same format you do. Skip accounts a hundred times bigger, because their reels win on name recognition, not craft, so copying them teaches the wrong lesson.
- Is my Apify token safe?
- Yes. It is saved on your own computer only and never shared. The prompt reminds you to make a fresh one at the end, which is good practice.
- This still feels too advanced. What do I do?
- Relax. There is one prompt, and I wrote it to do the hard part for you. Install the desktop app, paste my prompt, answer the questions, and drop a free key. It walks you through every step.
You came here from my reel and commented AGENTS, and this is your reward. This free guide is the what. If you want the how, done with you, so you build agents like this and launch fast, that is AI Mastery, the only AI course you will ever need. It teaches you to build anything with AI, agents, apps, automations, and sites, all in one place. Want me to build your agent team with you live on a call? I take a few 1:1 people each month. And if you would rather my team just build it for your business, that is Hire FabRich.