agentleFS
david-vrbadavid-vrba/claude-power-skills/skills/reel/SKILL.md

reel

Skill4 starsChanged 5 months agoMITView on GitHub

Analyze an Instagram Reel into an action report — deep mode (-h, default) does yt-dlp download, Whisper transcription, frame extraction, comments, and web research; fast mode (-l) does a Firecrawl + Playwright visual read only. Use when you want to know what a reel is about and whether it is worth acting on.

  • Installs packages

10 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

20 rules. 0 are common, 8 are distinctive, and 12 are very specific to this project.

  • 0

    Common

    Most of the 7 edited versions we read keep these.

  • 8

    Distinctive

    This author's own choices. Worth a look.

  • 12

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Only single-post URLs are supported.

    line 14
  2. Very specific:

    Check URL for /@, /channel/, /c/.

    line 45
  3. Distinctive:

    Success: no message needed.

    line 85
  4. Very specific:

    Check for success: Glob for reel_session*.info.json.

    line 89
  5. Very specific:

    Only run if reel_session*.info.json exists.

    line 93
  6. Very specific:

    Read reel_session_meta.txt with the Read tool.

    line 164
  7. Very specific:

    Only run if a video file exists (Phase 3 succeeded).

    line 202
  8. Very specific:

    If confirmed, install: $PYTHON -m pip install --user faster-whisper.

    line 207
  9. Distinctive:

    Step 2 — Transcribe: Run as a single bash block:

    line 209
  10. Very specific:

    Read reel_session_transcript.txt with the Read tool.

    line 239
  11. Distinctive:

    If a login wall is shown: extract whatever text is visible (preview frame, account name, captions) and note it.

    line 259
  12. Distinctive:

    Keep the browser from Phase 8 open.

    line 265
  13. Distinctive:

    If no frames exist (ffmpeg unavailable), the Playwright screenshot is the only visual.

    line 279
  14. Distinctive:

    If you can produce a more memorable slug from the report's main tool/topic or the first ~6 words of the caption, override it.

    line 347
  15. Very specific:

    Read the filename, then Write the report to the parent reports folder (you are inside research/reels/.tmp, so write to ../[filename]):

    line 349
  16. Very specific:

    Check URL for /@, /channel/, /c/.

    line 442
  17. Very specific:

    Use a Firecrawl scrape on the reel URL with formats: ["markdown", "links"], onlyMainContent: false.

    line 446
  18. Distinctive:

    If Firecrawl returns an error or empty content (Instagram login wall), note silently and continue — Phase 3 compensates.

    line 448
  19. Distinctive:

    If a login wall is shown, extract whatever text is visible and note it.

    line 459
  20. Very specific:

    Look for: text overlays (captions, titles, subtitles).

    line 465

“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Instagram Reel Intelligence Skill

Analyze a single Instagram Reel from every available signal and produce a direct, opinionated action report.

Arguments: [reel-url] [-l | -h]

  • -h or no flag → High mode (deep analysis). Run the HIGH MODE section below.
  • -l → Low mode (fast analysis). Run the LOW MODE section below.

Only single-post URLs are supported. /reel/ and /p/ are both valid; profile pages (/@, /channel/, /c/) are not — if given one, stop and say:

"This skill is for single reels only. Please provide a direct reel URL (e.g. instagram.com/reel/XXXXX/)."

Prerequisites: yt-dlp, ffmpeg (frames), faster-whisper (audio transcription), plus Firecrawl, Tavily, and Playwright MCP tools if available. Each step degrades gracefully when a tool is missing.

Output location: reports are saved under research/reels/ in your working directory (change the path to suit your setup). Scratch files live in research/reels/.tmp/ and are deleted at the end.


HIGH MODE (-h, default)

Full multi-signal analysis. Downloads the reel via yt-dlp, transcribes spoken audio with Whisper, extracts frames with ffmpeg, fetches comments, and captures a Playwright visual.

Phase 1: Check & Update yt-dlp

command -v yt-dlp

If not found, install:

  • Windows (winget): winget install yt-dlp.yt-dlp
  • Windows (pip fallback): pip install yt-dlp
  • macOS: brew install yt-dlp
  • Linux: pip3 install yt-dlp
yt-dlp -U

Phase 2: Detect Channel/Profile URLs

Check URL for /@, /channel/, /c/. If it is a profile page, stop with the single-reel message above. /reel/ and /p/ are allowed.

Phase 3: yt-dlp Download (Primary Source)

Step 0 — Pin the working directory. All reel_session.* / reel_frame_*.jpg scratch files are written here and globbed/cleaned up from here in later phases, so every phase must share one known CWD. Run this first and stay here:

mkdir -p "research/reels/.tmp"
cd "research/reels/.tmp"

Authentication: a cookies.txt file, not the live browser. Do NOT use --cookies-from-browser chrome — since Chrome 127 (mid-2024) Windows Chrome encrypts cookies with app-bound encryption that no external process can decrypt, and Chrome locks its cookie DB while running. The reliable path is an exported cookies.txt, which works with the browser open and needs no DB access. To create one: in a browser logged into Instagram, use the "Get cookies.txt LOCALLY" extension to export instagram.com cookies to ~/.claude/secrets/instagram_cookies.txt.

Run as a single bash block — it uses the cookie file if present, else goes cookieless, and reports which path it took:

COOKIES_FILE="$HOME/.claude/secrets/instagram_cookies.txt"
if [ -s "$COOKIES_FILE" ]; then
    echo "[reel] using cookies.txt (authenticated)"
    yt-dlp \
      --cookies "$COOKIES_FILE" \
      --write-comments \
      --write-info-json \
      --output "reel_session" \
      "REEL_URL"
else
    echo "[reel] no cookies file — running cookieless (comments limited, no private reels)"
    yt-dlp \
      --write-comments \
      --write-info-json \
      --output "reel_session" \
      "REEL_URL"
fi

--cookies passes an Instagram session to yt-dlp, bypassing login walls and unlocking real comment data + like counts. --write-comments reads comments into the info JSON — it does not post anything. It is present in both branches, so cookieless still attempts whatever comment data Instagram returns unauthenticated.

After the run, react to what happened — tell the user at most once, don't block:

  • No cookies file existed (cookieless branch ran): say once → "No Instagram cookies file found, so comments are limited and private reels are inaccessible. To fix permanently (works with the browser open): export instagram.com cookies once with the 'Get cookies.txt LOCALLY' extension to ~/.claude/secrets/instagram_cookies.txt."
  • Cookies file existed but yt-dlp errored with a login/auth wall (login required, rate-limit, Restricted Video, or an empty/zero-comment result on a clearly popular reel): cookies are likely stale. Say once → "Your Instagram cookies look stale — re-export them; Instagram wants a fresh session."
  • Success: no message needed.

If yt-dlp fails entirely (private reel, geo-blocked, unavailable): note it and continue — Phase 8 (Playwright) becomes the primary source.

Check for success: Glob for reel_session*.info.json. If found, Phase 3 succeeded.

Phase 4: Parse Metadata + Comments

Only run if reel_session*.info.json exists. Run as a single bash block:

PYTHON=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
PYTHONUTF8=1 $PYTHON -c "
import json, glob, sys, html

files = glob.glob('reel_session*.info.json')
if not files:
    print('ERROR: info JSON not found')
    sys.exit(1)

with open(files[0], encoding='utf-8') as f:
    info = json.load(f)

print('Title: ' + str(info.get('title', 'Unknown')))
print('Uploader: ' + str(info.get('uploader', 'Unknown')))
print('Duration: ' + str(info.get('duration_string', 'Unknown')))
print('Duration_secs: ' + str(info.get('duration', 30)))
print('Like_count: ' + str(info.get('like_count', 'Unknown')))
print('View_count: ' + str(info.get('view_count', 'Unknown')))

print()
print('=== DESCRIPTION ===')
desc = (info.get('description') or '').strip()
if desc:
    print(html.unescape(desc[:1000]))
    if len(desc) > 1000:
        print('...[truncated]')
else:
    print('[No description]')

comments = info.get('comments') or []
print()

# Engagement-bait detection: many creators run a 'comment WORD for the link' DM funnel,
# which floods comments with one repeated trigger word. That is a marketing mechanic,
# not organic sentiment — flag it so the report doesn't misread it as community reaction.
from collections import Counter
texts = [html.unescape((c.get('text') or '').strip()) for c in comments]
short = [t.lower() for t in texts if t and len(t.split()) <= 3]
if short:
    top_text, top_n = Counter(short).most_common(1)[0]
    if len(comments) >= 8 and top_n / len(comments) >= 0.35:
        pct = round(100 * top_n / len(comments))
        print('=== ENGAGEMENT-BAIT FLAG ===')
        print(f'~{pct}% of captured comments are the repeated trigger \"{top_text}\" — this is a '
              f'\"comment X for the link\" DM-funnel mechanic, NOT organic sentiment. Treat with skepticism.')
        print()

# Without auth, IG returns comment text but every like_count is 0, so a
# 'top comments' sort is meaningless. Detect that and label honestly.
have_likes = any((c.get('like_count') or 0) > 0 for c in comments)
print('=== COMMENTS ===' if have_likes else '=== COMMENTS (unranked — like counts unavailable without login) ===')
if comments:
    sorted_c = sorted(comments, key=lambda c: c.get('like_count', 0) or 0, reverse=True)[:20]
    for c in sorted_c:
        author = c.get('author', 'Unknown')
        text = html.unescape((c.get('text') or '').strip())
        likes = c.get('like_count', 0) or 0
        if not text:
            continue
        if have_likes:
            print('[' + str(likes) + ' likes] ' + author + ': ' + text[:300])
        else:
            print(author + ': ' + text[:300])
else:
    print('[Not available via yt-dlp — Playwright DOM snapshot will attempt to capture visible comments]')
" > reel_session_meta.txt

Read reel_session_meta.txt with the Read tool. If it contains ERROR: info JSON not found, Phase 3 failed — skip Phases 5 and 6.

Phase 5: Extract Frames

Only run if reel_session*.info.json exists. Run as a single bash block:

PYTHON=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
VIDEOFILE=$(ls reel_session.* 2>/dev/null | grep -Ev '\.(json|txt|jpg|webp|png)$' | head -1)

if [ -z "$VIDEOFILE" ]; then
    echo "No video file found — skipping frame extraction" > reel_session_frames.txt
    exit 0
fi

DURATION=$(PYTHONUTF8=1 $PYTHON -c "
import json, glob
files = glob.glob('reel_session*.info.json')
if files:
    d = json.load(open(files[0], encoding='utf-8')).get('duration', 30)
    print(int(d) if d else 30)
else:
    print(30)
")

if command -v ffmpeg &>/dev/null; then
    for PCT in 0 25 50 75; do
        TS=$(( DURATION * PCT / 100 ))
        ffmpeg -ss "$TS" -i "$VIDEOFILE" -frames:v 1 -q:v 2 "reel_frame_${PCT}.jpg" -y 2>/dev/null
    done
    echo "Frames extracted at 0% 25% 50% 75%" > reel_session_frames.txt
else
    echo "ffmpeg not available — install ffmpeg to enable frame extraction" > reel_session_frames.txt
fi

Phase 6: Whisper Transcription

Only run if a video file exists (Phase 3 succeeded). Uses faster-whisper — runs on GPU (CUDA) when available and falls back to CPU automatically.

Step 1 — Install check (do this BEFORE running the transcription block). Run PYTHONUTF8=1 $PYTHON -c "import faster_whisper". If it succeeds, go to Step 2. If it fails, ask the user:

"faster-whisper is not installed — the first install pulls the package (and, for GPU use, the CUDA runtime). Proceed?"

If confirmed, install: $PYTHON -m pip install --user faster-whisper. For NVIDIA GPU acceleration, also install nvidia-cublas-cu12 nvidia-cudnn-cu12==9.*. If declined, skip Phase 6 entirely and note "Audio transcription declined" in the report.

Step 2 — Transcribe. Run as a single bash block:

PYTHON=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
VIDEOFILE=$(ls reel_session.* 2>/dev/null | grep -Ev '\.(json|txt|jpg|webp|png)$' | head -1)
if [ -z "$VIDEOFILE" ]; then
    echo "No video file — Whisper skipped" > reel_session_transcript.txt
    exit 0
fi
if ! PYTHONUTF8=1 $PYTHON -c "import faster_whisper" 2>/dev/null; then
    echo "faster-whisper not installed — run: $PYTHON -m pip install --user faster-whisper" > reel_session_transcript.txt
    exit 0
fi
PYTHONUTF8=1 $PYTHON -c "
import sys
from faster_whisper import WhisperModel
audio, out = sys.argv[1], sys.argv[2]
try:
    model = WhisperModel('small', device='cuda', compute_type='float16')
except Exception:
    model = WhisperModel('small', device='cpu', compute_type='int8')
segments, info = model.transcribe(audio, vad_filter=True)
with open(out, 'w', encoding='utf-8') as f:
    for seg in segments:
        t = seg.text.strip()
        if t:
            f.write(t + '\n')
" "$VIDEOFILE" reel_session_transcript.txt || echo "Transcription failed" > reel_session_transcript.txt

Read reel_session_transcript.txt with the Read tool.

If the transcript is empty or whitespace-only, that is correct behavior for a silent or music-only reel — Whisper detected no speech. Do not treat it as an error. Carry [Silent reel — background music only, no speech detected] into the report's Raw Captures → Spoken transcript section.

Phase 7: Firecrawl Scrape — SKIP for Instagram

Firecrawl categorically blocks Instagram (We do not support this site) — a policy block, not a transient error. Skip this phase entirely and do not spend a tool call on it. The caption/links/account it would have provided are recovered from the yt-dlp description (Phase 4) and the Playwright DOM snapshot (Phase 8).

(If this skill is ever pointed at a non-Instagram host, or Firecrawl later adds Instagram support, re-enable a Firecrawl scrape with formats: ["markdown","links"], onlyMainContent: false, extracting caption / hashtags / mentioned links / account name.)

Phase 8: Playwright Visual Capture — ALWAYS RUN

This phase is mandatory on every high-mode analysis. Do NOT skip it because yt-dlp already returned comments. The screenshot and DOM caption captured here are independent signals (they confirm what the frames show and catch on-screen text the frames missed). The only reason to skip is if Playwright is unavailable.

  1. Navigate to the reel URL with browser_navigate.
  2. Wait for page load with browser_wait_for — selector video, timeout 3000ms. Prevents a blank screenshot on Instagram's JS-heavy load.
  3. Check for overlays with browser_snapshot. If a cookie consent dialog or modal is present ("Allow all cookies", "Accept", "Decline optional cookies"), dismiss it with browser_click. This snapshot also yields the caption / engagement counts — keep it.
  4. Screenshot with browser_take_screenshot. The image is returned inline — analyze it in Phase 9.
  5. Close browser with browser_close — but only after Phase 8b, if you run it. Keep the page open if you will run 8b.

If a login wall is shown: extract whatever text is visible (preview frame, account name, captions) and note it.

Phase 8b: Comment Recovery via Playwright — OPTIONAL

Run only when the yt-dlp comments from Phase 4 are absent or weak — no comments, or only the engagement-bait flood, or comments with no like counts when you want real community reaction. If Phase 4 already gave solid ranked comments, skip 8b. Skipping 8b does not skip the screenshot — that already happened in Phase 8.

Keep the browser from Phase 8 open. Instagram lazy-loads comments, so the Step 3 snapshot has caption + counts but zero comment text. To capture them:

  1. In the Step 3 snapshot, find the comment button (labeled like "Comment" with the count). browser_click it.
  2. browser_wait_for ~2s for the panel to render.
  3. Take a scoped snapshot to avoid the ~1,200-line full-feed dump: browser_snapshot with target set to the comment dialog/list container ref (or pass depth: 8 to cap tree size). Instagram auto-loads unrelated reels below the target; scoping keeps the snapshot to the active reel.
  4. To pull more than the first few comments, scroll the panel (browser_press_key PageDown, or browser_evaluate to scroll the container), then snapshot again. One extra scroll is usually enough.

Extract comment text from these scoped snapshots. Caveat: if the panel renders to canvas rather than accessible DOM, note "comments visible in screenshot but not extractable from DOM" and move on. Then close the browser.

Phase 9: Analyze Frames

Glob for reel_frame_*.jpg. If frames exist, Read each in order: reel_frame_0.jpg (opening), 25, 50, 75 (near end). Also analyze the Playwright screenshot from Phase 8.

For each frame, extract: all visible text overlays (on-screen captions, subtitles, titles); any tool/product/website names shown; any URLs or handles; the visual subject; any UI, code, or before/after being shown.

If no frames exist (ffmpeg unavailable), the Playwright screenshot is the only visual.

Phase 10: Web Research

From Phases 4–9, compile every tool, product, website, or concept identified. For each significant one (skip generic words), use WebSearch (or Tavily/Firecrawl search if available):

  • What it is / what it does
  • Pricing or access model (free / paid / open-source)
  • Relevance to the reader's workflow and developer productivity

Limit to 1 search per item.

Phase 11: Synthesize → Action Report

Combine all signals: transcript, comments, caption, visual frames, web research. Be direct and opinionated. Write for a technical reader who values speed and signal over completeness — judge relevance against their actual tools and workflow.

## What this is about
[1 sentence — the reel's topic and the specific angle or claim being made]

## The core idea
[2–4 sentences — what's being shown or recommended, and why it's framed as interesting. Draw from the transcript if available — spoken words are usually more specific than captions.]

## What was identified
- **Tool / Product / Concept**: [name] — [what it is, one line]
- [repeat for each significant item]
- **Source account**: [Instagram handle if known]

## What people are saying
[Only include if comments were found. Summarize sentiment — is the community validating the claim, calling it out, sharing results? Include 1–2 direct quotes if useful. If no comments, omit this section.]

## Why this is interesting
[Honest take: what makes this genuinely good or novel. Be specific — don't hedge.]

## Relevance to your workflow
[Does this apply to your tools and workflow? Be direct about fit or lack of fit.]

## Verdict
**[DO IT / BACKLOG / SKIP]**
[1–3 sentences explaining why. If DO IT: the first concrete step.]

## Watch out for
[Caveats, limitations, assumptions the reel glosses over. If nothing significant, say "None."]

Phase 12: Save to Disk

Generate the filename as a single bash block:

PYTHON=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
TODAY=$(date +%Y-%m-%d)
SLUG=$(PYTHONUTF8=1 $PYTHON -c "
import re, json, glob
files = glob.glob('reel_session*.info.json')
info = json.load(open(files[0], encoding='utf-8')) if files else {}
title = info.get('title') or ''
slug = re.sub(r'[^a-z0-9]+', '-', title.lower()).strip('-')[:60]
# Instagram has no real title — yt-dlp fills it with 'Video by <uploader>',
# which makes a useless, colliding slug. Fall back to the reel id instead.
if not slug or re.match(r'^(video|reel)-by-', slug):
    rid = info.get('id') or info.get('display_id') or ''
    slug = re.sub(r'[^a-z0-9]+', '-', str(rid).lower()).strip('-')[:60] or 'reel'
print(slug)
")
echo "${TODAY}_${SLUG}.md" > reel_session_filename.txt
cat reel_session_filename.txt

If you can produce a more memorable slug from the report's main tool/topic or the first ~6 words of the caption, override it. If info JSON never existed (yt-dlp failed entirely), build the slug from the main tool/topic in the report.

Read the filename, then Write the report to the parent reports folder (you are inside research/reels/.tmp, so write to ../[filename]):

---
source: instagram-reel
url: [REEL_URL]
date: TODAY
account: [account name if known]
verdict: [DO IT / BACKLOG / SKIP]
mode: high
---

# [Main topic / tool name]

**URL:** [REEL_URL] | **Account:** [handle] | **Date analyzed:** TODAY

## What this is about
[from Phase 11]

## The core idea
[from Phase 11]

## What was identified
[from Phase 11]

## What people are saying
[from Phase 11 — omit if no comments were found]

## Why this is interesting
[from Phase 11]

## Relevance to your workflow
[from Phase 11]

## Verdict
[from Phase 11]

## Watch out for
[from Phase 11]

---

## Raw Captures

### Caption / DOM text
[raw text from Playwright DOM snapshot]

### Spoken transcript
[Whisper output — omit if transcription was skipped]

### Comments
[raw comment data from yt-dlp or Playwright DOM — omit if none found]

### Visual notes
[frame-by-frame observations: 0%, 25%, 50%, 75%]

Tell the user the save path (research/reels/[filename]).

Phase 13: Cleanup

rm -f reel_session.* reel_frame_*.jpg \
  reel_session_transcript.txt reel_session_meta.txt \
  reel_session_frames.txt reel_session_filename.txt

The saved .md file is kept permanently.

High-Mode Edge Cases

SituationHow to handle
yt-dlp fails entirelySkip Phases 4–6. Playwright (Phase 8) becomes the only source. Note in report.
No cookies.txt fileyt-dlp runs cookieless. Comments limited, no private reels. Tell user once how to set up ~/.claude/secrets/instagram_cookies.txt.
Cookies present but auth-walledCookies are stale — tell user once to re-export. Proceed with whatever data came back.
Comments are engagement-baitENGAGEMENT-BAIT FLAG fired in Phase 4 — report it as a DM-funnel mechanic, not sentiment. Optionally run Phase 8b.
No comments anywhereOmit "What people are saying".
ffmpeg not availableSkip frame extraction. Playwright screenshot is the only visual.
Whisper declinedSkip transcription. Note "Audio transcription declined".
Login wall on InstagramPlaywright extracts whatever is visible. Note in report.
Purely visual reel, no speechWhisper produces little — fine, visual frames carry it.
Non-English reelWhisper small supports many languages. Note detected language.
/p/ URLTreat same as /reel/ — allow and proceed.

LOW MODE (-l)

Fast analysis. Firecrawl for caption, Playwright for visual capture, web research on identified tools. No download, no audio transcription, no frame extraction. Use when you want a quick read without waiting for yt-dlp or Whisper.

Phase 1: Detect Channel/Profile URLs

Check URL for /@, /channel/, /c/. If it is a profile page, stop with the single-reel message. /reel/ and /p/ are allowed.

Phase 2: Scrape Page Text (Firecrawl)

Use a Firecrawl scrape on the reel URL with formats: ["markdown", "links"], onlyMainContent: false. Extract: Caption, Hashtags, Mentioned links, Account name.

If Firecrawl returns an error or empty content (Instagram login wall), note silently and continue — Phase 3 compensates.

Phase 3: Visual Capture (Playwright)

  1. Navigate with browser_navigate.
  2. Wait with browser_wait_for — selector video, timeout 3000ms.
  3. Check overlays with browser_snapshot; dismiss any cookie/consent modal with browser_click.
  4. DOM snapshot with browser_snapshot (or reuse Step 3). Captures accessible DOM text — often caption + top comment text even without login.
  5. Screenshot with browser_take_screenshot (returned inline — analyze in Phase 4).
  6. Close browser with browser_close.

If a login wall is shown, extract whatever text is visible and note it.

Phase 4: Read the Screenshot

Analyze the inline screenshot. Fallback: if it is blank, mostly dark, or a loading state, use any available vision-capable LLM/MCP with the DOM text and caption to infer what the reel is about.

Look for: text overlays (captions, titles, subtitles); tool/product/website names; URLs or handles; the visual subject; any before/after, code snippet, or UI shown.

Phase 5: Web Research

From Phases 2–4, compile every tool, product, website, or concept. For each significant one, use WebSearch (or Tavily/Firecrawl search): what it is, pricing/access model, relevance to the reader's workflow. Limit to 1 search per item. Do not spiral.

Phase 6: Synthesize → Action Report

Combine Phases 2–5. Be direct and opinionated; write for a technical reader who values speed and signal over completeness.

## What this is about
[1 sentence]

## The core idea
[2–4 sentences]

## What was identified
- **Tool / Product / Concept**: [name] — [one line]
- [repeat]
- **Source account**: [handle if known]

## Why this is interesting
[Specific, no hedging]

## Relevance to your workflow
[Direct about fit or lack of fit]

## Verdict
**[DO IT / BACKLOG / SKIP]**
[1–3 sentences. If DO IT: first concrete step.]

## Watch out for
[Caveats. If nothing, say "None."]

Phase 7: Save to Disk

mkdir -p "research/reels"

Generate a slug from the main topic/tool (lowercase, hyphens, max 6 words). Use today's date: YYYY-MM-DD_slug.md. Write to research/reels/YYYY-MM-DD_slug.md:

---
source: instagram-reel
url: [REEL_URL]
date: YYYY-MM-DD
account: [account name if known]
verdict: [DO IT / BACKLOG / SKIP]
mode: low
---

# [Main topic / tool name]

**URL:** [REEL_URL] | **Account:** [handle] | **Date analyzed:** YYYY-MM-DD

## What this is about
[from Phase 6]

## The core idea
[from Phase 6]

## What was identified
[from Phase 6]

## Why this is interesting
[from Phase 6]

## Relevance to your workflow
[from Phase 6]

## Verdict
[from Phase 6]

## Watch out for
[from Phase 6]

---

## Raw Captures

### Caption / DOM text
[raw text from Firecrawl / Playwright DOM snapshot]

### Visual notes
[what the screenshot showed — text overlays, UI, etc.]

Tell the user the save path. No temp files to clean — screenshot data is inline.

Low-Mode Edge Cases

SituationHow to handle
Login wall on InstagramUse whatever is visible + caption from Firecrawl if it worked. Note in report.
Purely visual, no textDescribe what's shown; research the visual subject with WebSearch.
No tool/product — just an ideaSkip Phase 5 search. Focus on the concept and its applicability.
Non-English reelUse available content; note language; translate key terms if needed.
Firecrawl returns login wall HTMLIgnore it. Playwright screenshot is primary.
Screenshot blank or loadingUse DOM snapshot text; vision-LLM fallback if needed.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.