ReelQL
SkillFiles & storageAnalyze any video link (YouTube, TikTok, Vimeo, media file): story, brands, products, emotional arc, key moments, transcript. Use whenever the user shares a video URL.
Use ReelQL in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add ReelQL and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the ReelQL skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by tomascupr/reelql in skills/reelql/SKILL.md and read by Ahel’s review.
ReelQL turns a video URL into one JSON document. It needs the environment variable REELQL_API_KEY, a personal key that anyone can get for free with 10 minutes of video. The scripts check their own keys; when one is missing they print how to get it. Pass that on to the user as it is and wait for the key. Never inspect REELQL_API_KEY or TYPESAFE_API_KEY yourself (no echo, printenv, env, cat .env, not even to test that one is set), and never write a key into a file or command line.
Run videos
Run the script in this skill's directory, in the foreground (it finishes in a minute or two), from a scratch directory:
bash <this skill's directory>/scripts/reelql.sh "<url>" ["<url>" ...]
It saves each result as reelql-1.json, reelql-2.json, ... in URL order, five videos at a time, and prints done or failed with the reason for each one. A 4-minute video takes about 25 s, a 15-minute one about a minute. It needs curl and jq.
A result is large: the transcript alone can be tens of kB. Read only the parts you need with jq, for example:
jq '.result.analysis | {summary, advertiser, brands, products, emotional_arc, key_moments, on_screen_text}' reelql-1.json
jq '.result.video | {title, channel, platform, duration_s, stats}' reelql-1.json
jq -r '.result.speech.transcript[] | "[\(.start)] \(.speaker): \(.text)"' reelql-1.json
Credit
Each video costs its length, at $0.05 a minute, from the key's prepaid credit. When a video is refused with 402 (no credit left, or the video is longer than the credit), tell the user and offer a payment link:
bash <this skill's directory>/scripts/reelql.sh --topup <dollars, 5 to 500>
It prints a Stripe payment page for the user to open in a browser ($5 buys 100 minutes) and the minutes left. Never pay yourself, and don't pick an amount the user hasn't agreed to.
What to tell the user
If the user asked something specific ("who is the advertiser?", "when does the logo appear?"), answer just that from the fields that hold it, with timestamps.
If they only shared a link or said "analyze this", give this brief, in this order, and skip any part the video has nothing for:
- What it is: one sentence, with the platform, channel and length.
- Who's selling what: the advertiser, and each product with the time it first appears.
- The story: the premise and how it unfolds, in 2-3 sentences.
- How it should feel: the emotional arc as a chain (curiosity → anticipation → excitement), with the moment behind each shift.
- Key moments: at most 5 lines, formatted as
m:ssthen what happens. - On-screen text worth knowing (dates, prices, calls to action), and the views and likes if the platform reports them.
Keep it under about 20 lines. Then suggest one next step that fits the video, in a sentence:
- An ad or a sponsored post: rank it against their brief with Jev, or check it for brand safety (below).
- A social video with products or brands on screen: offer to run more links they send (the creator's other posts, a hashtag, a competitor) and list the brands and products that keep appearing.
- Mostly talk (a lecture, a podcast, a tutorial): say that the transcript carries it, and offer the transcript or a summary of what was said.
Or offer a follow-up about this video that the data can answer: the full transcript, scene by scene, the cast.
How many of the videos each brand appears in, most first:
jq -r '.result.analysis | [(.brands // [])[], ((.products // [])[] | .brand // empty)] | unique[]' reelql-*.json | sort | uniq -c | sort -rn
Judge or rank videos with Jev (optional)
If the user wants a judgment rather than a description, and TYPESAFE_API_KEY is set, use Jev (TypeSafe's judgment model). Judgments include "is this on brief?", "rank these ads", "which is safest?" and "which one should we run?".
- Run all the videos through
scripts/reelql.shin one call. - Pass the result files to the
scripts/jev.pyscript in this skill's directory:
uv run --with typesafe-sdk python <this skill's directory>/scripts/jev.py "<the brief, in the user's words>" reelql-*.json
It prints a table ranked by the probability that each video is on brief, with hook, product and payoff scores (0 to 1) and the probability that the content is unsafe. Show the table, then say in one or two sentences why the top video wins and what holds back the rest, using the ReelQL fields. Jev's numbers are judgments, not measurements: say so if the user is about to act on a close call. Without TYPESAFE_API_KEY, judge from the ReelQL fields yourself and say that Jev would give calibrated scores.
What the result holds
.result has schema_version, then:
video: title, channel, duration_s, platform, url, upload_date, description (the caption), tags, music (TikTok sound), stats (views, likes, comments, as reported at fetch time;nullwhere the platform does not give one).speech.transcript[]:{start, end, speaker, text}, speakers labelledSPEAKER_00...analysis:summarystory: premise, tone, themes, arccharacters[]:name_or_label, appearance, role, first_seen_saudio: music, sound effects, voiceover, toneadvertiser,brands[],products[](with each appearance's time and prominence)chapters[]: one per 30 s,{start_s, end_s, title, summary}scenes[],key_moments[]emotional_arc[]: what the viewer is meant to feel,{t_s, emotion, intensity 1-5, cue}on_screen_text[]
All times are seconds from the start of the video. A person's name appears only when the title, channel, on-screen text or transcript contains it; otherwise name_or_label is a short description ("young girl"). advertiser, brand and mood are null when nothing in the video supports them. Report these as the video's own evidence, not as verified facts.
Errors
400: the URL was refused (private address, not http(s), a live stream, longer than 30 minutes, over 4 GB, or not a video). The reason is in.detail.401: missing or wrong key.402: not enough credit for this video. The reason says how many minutes it needs and how many are left; see Credit.429: the key already has 5 jobs queued or running, for example from another session. Wait and run again.503: ReelQL is busy. Wait the seconds in theRetry-Afterheader (60) and submit again. While a job isqueued, itspositionsays how many jobs are ahead of it, counting itself.404on a job: wrong id, older than a day, or the service restarted (jobs are kept in memory). Submit again.- A
failedjob:.errorsays why (for example a deleted or region-blocked post).
Signals
- GitHub stars
- 28
- Forks
- 1
- Last commit
- Sep 2026
Ahel review
K6low
bundled executables the agent is told to run
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Item type
- skill
- Key
reelql- Source
- github.com/tomascupr/reelql