New: Earn 20% as an AgentAlley affiliate. Share your link and earn on every sale you refer. Join now New: Earn 20% as an affiliate. Join now

Detect non-organic views / fake engagement / bot comments

Channel Authenticity

by ThoughtLeaders-io · MIT license · ★ 25 on GitHub · updated Sep 23

Channel Authenticity cover

Detect non-organic views / fake engagement / bot comments on a YouTube channel before booking (or after delivering) a sponsorship. Use when asked to vet a channel, check if views/comments are real, investigate suspicious engagement,…

---
name: tl-channel-authenticity
tl-blurb: vet a channel for fake views
description: >
  Detect non-organic views / fake engagement / bot comments on a YouTube
  channel before booking (or after delivering) a sponsorship. Use when asked
  to vet a channel, check if views/comments are real, investigate suspicious
  engagement, audit a sponsorship delivery, or whenever someone shares a
  YouTube channel/handle/URL and asks "is this real / safe to buy an ad on".
  Triggers: "fake views", "bot comments", "non-organic", "is this channel
  legit", "vet this channel", "engagement looks off", "audit this sponsorship".
---

# Channel Authenticity

Takes a channel (handle / URL / numeric id / name) — or `adlink:<id>` for a
sponsorship drill-down — and returns a 0–100 authenticity score plus ranked
red-flag findings. Built and calibrated from real bought-view and comment-farm

Overview

Takes a channel (handle / URL / numeric id / name) — or adlink:<id> for a sponsorship drill-down — and returns a 0–100 authenticity score plus ranked red-flag findings. Built and calibrated from real bought-view and comment-farm investigations.

Manual install (npx, ZIP)
Claude Codenpx skills add ThoughtLeaders-io/thoughtleaders-cli --skill tl-channel-authenticity -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/ThoughtLeaders-io/thoughtleaders-cli/tar.gz/c7a01646c1b3 \ | tar -xz -C ~/.claude/skills --strip-components=2 thoughtleaders-cli-c7a01646c1b3/skills/tl-channel-authenticity
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/493fa32966651de93edc/tl-channel-authenticity.zip" -OutFile "$env:TEMP\tl-channel-authenticity.zip"; Expand-Archive "$env:TEMP\tl-channel-authenticity.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md6.1 KB
  • .gitignore121 B
  • references/4 files · 14.0 KB
  • scripts/13 files · 82.6 KB
Read the files here
ThoughtLeaders-io/c7a016419 files
SKILL.md
Show the full text129 lines

Channel Authenticity

Takes a channel (handle / URL / numeric id / name) — or adlink:<id> for a sponsorship drill-down — and returns a 0–100 authenticity score plus ranked red-flag findings. Built and calibrated from real bought-view and comment-farm investigations.

Hard rules

  • One mode. Every run does everything. No flags, no opt-in tiers. Groups A, B, and C all run, every time.
  • Comment scraping (Group C) is mandatory and never skipped. Metrics and view-curves can be hand-waved ("the algorithm", "we ran ads"); reading what the audience actually says is the only direct proof. A run without it is invalid.
  • Data access is CLI-only. Everything goes through tl_cli.py and the tl CLI (tl db pg/fb/es, tl channels similar).
  • Do all data processing with the "utf-8" encoding explicitly in all scripts you create.

Setup check

cd .claude/skills/tl-channel-authenticity/scripts
python3 tl_cli.py preflight        # must print "OK"

If this errors with cli_unavailable, tell the user to run tl auth login (or set TL_API_KEY). Comment scraping additionally needs yt-dlp (pip install yt-dlp) — it uses the android InnerTube client so no cookies or API key are required.

How to run (three phases — a classifier subagent sits between two CLI passes)

Phase 1 — collect. From the scripts/ dir:

python3 analyze_channel.py "<handle|url|id|name|adlink:ID>"

This runs Groups A + B + C(rule-based), scrapes ≥10 latest longforms (+ highest-view + most-recently-sponsored), and prints a JSON envelope with state_path, llm_batch_path, and llm_batch_size.

If the ref matches multiple channels (common for names with localized dupes), Phase 1 exits (code 4) with {"error":"ambiguous_channel", "candidates":[{id,name,subscribers}…]} instead of guessing. Show the candidates to the user — they're ordered by subscriber count, highest first (the most likely intended) — let them pick, then re-run Phase 1 with that numeric id.

Phase 2 — classify comments (run the subagent TWICE). Read llm_batch_path (a JSON array of {i, text, author}) and send it to the youtube-comment-classifier agent via the Agent tool (subagent_type: youtube-comment-classifier) twice — two separate calls on the same batch. Prepend one context line: channel niche: cat <content_category>, language <language> (both values are in the envelope). Each call returns a strict JSON array [{"i":N,"label":"organic|generic-template|bot-like|promotional|spam"}]; save each reply verbatim to its own file (e.g. /tmp/ca_llm1.json, /tmp/ca_llm2.json).

Why twice: single-pass LLM labeling wobbles ±10pts, so finalize majority-votes the two passes to keep the reported organic share stable. Sophisticated AI-comment farms read as clean English at normal volume — only the classifier catches them, so this pass is essential.

If the batch is empty (channel had almost no comments), skip the subagent and pass an empty array [] — near-zero comments is itself the loudest signal, and Group C already penalizes it.

Phase 3 — finalize (pass both classifier files):

python3 analyze_channel.py --finalize <state_path> /tmp/ca_llm1.json /tmp/ca_llm2.json

This applies the LLM verdict, computes the composite score, writes the final JSON + markdown report to /tmp, and prints the report. Present that report to the user (it's already formatted — peer comparison, group scores, ranked flags, verdict).

Scoring (see references/scoring.md)

Three groups, each scored 0–100 independently (start at 100, subtract fixed per-flag penalties). Final = simple mean of the three. Two hard overrides force FRAUD_LIKELY (score capped at 39) regardless of the mean: (1) Group C — non-organic audience (<30% organic from the classifier, or a dead comment section); (2) Group B — concealed/misrepresented performance (≥2 sold+published sponsored videos deleted/unlisted, or one with ≥5k views; or ≥3 high-view videos scrubbed with ≥15% of tracked views gone).

Bands: ≥90 CLEAN · ≥70 MINOR_FLAGS · ≥40 MIXED · <40 FRAUD_LIKELY.

What each group checks

  • Group A — engagement & peer ratios (engagement_ratios.py, peer_cohort.py): like/comment rates measured against a niche-matched peer baseline, plus audience-size sanity checks across longforms vs shorts.
  • Group B — view-curve anomalies + video integrity (view_curves.py, anomaly_detector.py, video_integrity.py): view-over-time curves that don't behave like organic growth (bursts without engagement, guarantee cliffs at round numbers, frozen likes, subs flat while views surge), plus intent-aware detection of deleted/unlisted videos used to conceal or misrepresent performance (benign re-uploads are excluded).
  • Group C — comment content (comment_scraper.py, comment_analyzer.py
    • classifier subagent): whether the comments are a real, engaged audience — scarcity vs views, templating and near-duplicates, language mismatch, bot-handle patterns, and the classifier's organic-share verdict.

Full catalogue + thresholds: references/red-flags.md. The exact tl queries each check issues live in the scripts; the underlying channel/video/adlink schema is documented in the tl skill (skills/tl/references/).

After a run

Offer to log the verdict (channel, score, top flags, date) to a "Channel Vetting Log" sheet via the gws skill if the user wants an audit trail. If you discover a new robust signal, add it to references/red-flags.md and a penalty to references/scoring.md (self-improvement).

1---
2name: tl-channel-authenticity
3tl-blurb: vet a channel for fake views
4description: >
5 Detect non-organic views / fake engagement / bot comments on a YouTube
6 channel before booking (or after delivering) a sponsorship. Use when asked
7 to vet a channel, check if views/comments are real, investigate suspicious
8 engagement, audit a sponsorship delivery, or whenever someone shares a
9 YouTube channel/handle/URL and asks "is this real / safe to buy an ad on".
10 Triggers: "fake views", "bot comments", "non-organic", "is this channel
11 legit", "vet this channel", "engagement looks off", "audit this sponsorship".
12---
13 
14# Channel Authenticity
15 
16Takes a channel (handle / URL / numeric id / name) — or `adlink:<id>` for a
17sponsorship drill-down — and returns a 0–100 authenticity score plus ranked
18red-flag findings. Built and calibrated from real bought-view and comment-farm
19investigations.
20 
21## Hard rules
22 
23- **One mode. Every run does everything.** No flags, no opt-in tiers. Groups
24 A, B, and C all run, every time.
25- **Comment scraping (Group C) is mandatory and never skipped.** Metrics and
26 view-curves can be hand-waved ("the algorithm", "we ran ads"); reading what
27 the audience actually says is the only direct proof. A run without it is
28 invalid.
29- **Data access is CLI-only.** Everything goes through `tl_cli.py` and the
30 `tl` CLI (`tl db pg/fb/es`, `tl channels similar`).
31- Do all data processing with the "utf-8" encoding explicitly in all scripts
32 you create.
33 
34## Setup check
35 
36```bash
37cd .claude/skills/tl-channel-authenticity/scripts
38python3 tl_cli.py preflight # must print "OK"
39```
40If this errors with `cli_unavailable`, tell the user to run `tl auth login`
41(or set `TL_API_KEY`). Comment scraping additionally needs `yt-dlp`
42(`pip install yt-dlp`) — it uses the android InnerTube client so **no cookies
43or API key are required**.
44 
45## How to run (three phases — a classifier subagent sits between two CLI passes)
46 
47**Phase 1 — collect.** From the `scripts/` dir:
48```bash
49python3 analyze_channel.py "<handle|url|id|name|adlink:ID>"
50```
51This runs Groups A + B + C(rule-based), scrapes ≥10 latest longforms
52(+ highest-view + most-recently-sponsored), and prints a JSON envelope with
53`state_path`, `llm_batch_path`, and `llm_batch_size`.
54 
55If the ref matches **multiple channels** (common for names with localized
56dupes), Phase 1 exits (code 4) with `{"error":"ambiguous_channel",
57"candidates":[{id,name,subscribers}…]}` instead of guessing. Show the
58candidates to the user — they're ordered by subscriber count, highest first
59(the most likely intended) — let them pick, then re-run Phase 1 with that
60numeric id.
61 
62**Phase 2 — classify comments (run the subagent TWICE).** Read
63`llm_batch_path` (a JSON array of `{i, text, author}`) and send it to the
64`youtube-comment-classifier` agent via the **Agent tool**
65(`subagent_type: youtube-comment-classifier`) **twice** — two separate calls on
66the same batch. Prepend one context line: `channel niche: cat
67<content_category>, language <language>` (both values are in the envelope).
68Each call returns a strict JSON array
69`[{"i":N,"label":"organic|generic-template|bot-like|promotional|spam"}]`; save
70each reply verbatim to its own file (e.g. `/tmp/ca_llm1.json`,
71`/tmp/ca_llm2.json`).
72 
73Why twice: single-pass LLM labeling wobbles ±10pts, so finalize majority-votes
74the two passes to keep the reported organic share stable. Sophisticated
75AI-comment farms read as clean English at normal volume — only the classifier
76catches them, so this pass is essential.
77 
78If the batch is empty (channel had almost no comments), skip the subagent and
79pass an empty array `[]` — near-zero comments is itself the loudest signal,
80and Group C already penalizes it.
81 
82**Phase 3 — finalize** (pass both classifier files):
83```bash
84python3 analyze_channel.py --finalize <state_path> /tmp/ca_llm1.json /tmp/ca_llm2.json
85```
86This applies the LLM verdict, computes the composite score, writes the final
87JSON + markdown report to `/tmp`, and prints the report. Present that report
88to the user (it's already formatted — peer comparison, group scores, ranked
89flags, verdict).
90 
91## Scoring (see references/scoring.md)
92 
93Three groups, each scored 0–100 independently (start at 100, subtract fixed
94per-flag penalties). **Final = simple mean of the three.** Two hard
95overrides force `FRAUD_LIKELY` (score capped at 39) regardless of the mean:
96(1) Group C — non-organic audience (<30% organic from the classifier, or a
97dead comment section); (2) Group B — concealed/misrepresented performance
98(≥2 sold+published sponsored videos deleted/unlisted, or one with ≥5k views;
99or ≥3 high-view videos scrubbed with ≥15% of tracked views gone).
100 
101Bands: ≥90 CLEAN · ≥70 MINOR_FLAGS · ≥40 MIXED · <40 FRAUD_LIKELY.
102 
103## What each group checks
104 
105- **Group A — engagement & peer ratios** (`engagement_ratios.py`,
106 `peer_cohort.py`): like/comment rates measured against a niche-matched peer
107 baseline, plus audience-size sanity checks across longforms vs shorts.
108- **Group B — view-curve anomalies + video integrity** (`view_curves.py`,
109 `anomaly_detector.py`, `video_integrity.py`): view-over-time curves that
110 don't behave like organic growth (bursts without engagement, guarantee
111 cliffs at round numbers, frozen likes, subs flat while views surge), plus
112 intent-aware detection of deleted/unlisted videos used to conceal or
113 misrepresent performance (benign re-uploads are excluded).
114- **Group C — comment content** (`comment_scraper.py`, `comment_analyzer.py`
115 + classifier subagent): whether the comments are a real, engaged audience —
116 scarcity vs views, templating and near-duplicates, language mismatch,
117 bot-handle patterns, and the classifier's organic-share verdict.
118 
119Full catalogue + thresholds: `references/red-flags.md`. The exact `tl` queries
120each check issues live in the scripts; the underlying channel/video/adlink
121schema is documented in the `tl` skill (`skills/tl/references/`).
122 
123## After a run
124 
125Offer to log the verdict (channel, score, top flags, date) to a "Channel
126Vetting Log" sheet via the `gws` skill if the user wants an audit trail.
127If you discover a new robust signal, add it to `references/red-flags.md` and
128a penalty to `references/scoring.md` (self-improvement).
129 
View all files on GitHub →

Details

Updated
Sep 23, 2026
License
MIT
Stars on the repo
★ 25
Checked
Source
ThoughtLeaders-io/thoughtleaders-cli ↗
Creator
ThoughtLeaders-io · 4 listings
View creator

Similar skills

See all →
SkillEvaluate a creator, influencerAudience researchScrapeCreators/social-media-research-skills · by ScrapeCreatorsUse when the user wants to evaluate a creator, influencer, or brand audience using public profile signals, TikTok audience demographics, follower/following data, comments, geography, language, and content fit. Helps judge sponsorship and market fit.★ 2.6k GitHub starsSkillScores and ranks influencers for brand partnership fitInfluencer fit scoringwriter/skills · by writerScores and ranks influencers for brand partnership fit using a multi-dimensional framework covering audience alignment, engagement quality, brand safety, content relevance, and commercial viability for CPG and retail e-commerce campaigns. Use when evaluating potential influencer partners, building shortlists, or comparing candidates. Triggers on requests for influencer evaluation, creator partnerships, influencer scoring, KOL assessment, or ambassador selection.★ 7 GitHub starsSkillRun influencer, creator, or ambassador partnershipsInfluencer & Creator Marketingcoreyhaines31/marketingskills · by coreyhaines31When the user wants to run influencer, creator, or ambassador partnerships to promote their product — finding and vetting partners, structuring deals, briefing creators, disclosure compliance, and measuring ROI. Also use when the user mentions 'influencer mark★ 51.1k GitHub starsMCPTwitter AI influencer engagement specialistTwitter AI influencer managerdavila7/claude-code-templates · by davila7Twitter AI influencer engagement specialist. Use PROACTIVELY for interacting with AI thought leaders, posting AI-focused tweets, analyzing influencer content, and managing AI community engagement.★ 32.3k GitHub starsSkillAnalyze my target audienceAudience mapperaaron-he-zhu/aaron-marketing-skills · by aaron-he-zhuUse when the user asks to "analyze my target audience", "build an audience profile for influencer targeting", "research a niche community", or "deep-dive a subculture before partnering with creators"; in audience mode produces demographic/psychographic profiles, a platform-priority matrix, named personas, and an influencer-selection criteria set, and in niche mode produces a community map, culture decode (language/norms/taboos), key-voice tiers, a Brand Fit Score, and a phased entry strategy. Not for finding specific creators to contract — use influencer-discovery; not for scoring a shortlist on Suitability — use fit-scorer. 目标受众画像/人群分析 · 细分社群/亚文化调研★ 2.9k GitHub starsSkillScore this influencer, rank these creators for our campaignFit scoreraaron-he-zhu/aaron-marketing-skills · by aaron-he-zhuUse when the user asks to "score this influencer", "rank these creators for our campaign", or "tell me which influencer is the best fit"; produces the typed STAR Suitability (S) read plus a separately labeled campaign-fit ranking without mixing campaign-specific commercial fit into the Suitability read. Not for finding new influencers — use influencer-discovery; not for sending outreach — use outreach-manager. 达人适配度评分/创作者筛选排名★ 2.9k GitHub stars

More from ThoughtLeaders-io

SkillSave the results of an in-chat data-exploration sessionPath A — List-styleThoughtLeaders-io/thoughtleaders-cli · by ThoughtLeaders-ioSave the results of an in-chat data-exploration session as a TL report. Triggers when the user wants to persist a channels / brands / videos (uploads) / sponsorships list or filtered set they've been working with — phrases like "save this as a report", "save the list", "turn this into a campaign", "persist this", "make a report from what you found", "save the result", "I want to come back to this".★ 25 GitHub starsSkillTurn a topic into a validated content filtertl-keyword-research — topic → validated filter set + the results you chooseThoughtLeaders-io/thoughtleaders-cli · by ThoughtLeaders-ioTurn a topic into a *validated* content filter and the channels it selects. Invoke whenever the user wants to find videos or channels by what they are about — topics, concepts, niches, not IDs or names: "a group/set of keywords for <topic>", "keywords that represent <topic> content", "find content/channels about <topic>", "find investing channels" — or when you'd otherwise hand-compose a `tl db es` content search. It expands the topic into candidate keywords (with a gated web lookup for post-cutoff entities), probes Elasticsearch for each (counts + samples), validates matches against the user's stated intent, refines a boolean filter over ≥3 rounds, and delivers a keyword-group filter set + a clickable report link + the results the user chose: trend data at the video level (matching uploads + prevalence), or channel targets classified by topic intensity (core / recurring / one-off) and context-validated with cheap agents, or both. It ASKS which deliverable and which run mode (quick single pass vs deep ≥3-round refinement) the user wants whenever the request doesn't say — never a silent default; `autonomous` / `--auto` means deep + both deliverables with every pause skipped. Keyword-distribution output (counts per keyword) is OPT-IN — only when the user explicitly asks for "keyword counts / distribution / how common is X". Also invoke for HELP asks about this skill — "help", "how does keyword research work", "what are my options", "describe this skill" — answered free from the built-in guide, no queries run.★ 25 GitHub starsSkillExternal brand-user performance reportTop Partnerships (Brand-side)ThoughtLeaders-io/thoughtleaders-cli · by ThoughtLeaders-ioExternal brand-user performance report. Ranks a brand's sponsorships by effective CPM once the sponsored videos went live, and compares live eCPM against the sold-date projection. Use whenever a brand user asks "which of my sponsorships performed best", "top partnerships this year", "best ROI deals", "effective CPM on my deals", "which sponsorships overperformed", "/top-partnerships", or any variation of "show me my best-performing sponsorships". This is the brand-side equivalent of internal performance reporting — fire it eagerly any time a brand wants to look back at their booked deals through a performance lens, even if they don't say the words "CPM" or "eCPM".★ 25 GitHub stars