| name | ask-yt |
| description | Ask YouTube's built-in Gemini AI about video content using CDP automation. Use when user provides a YouTube URL and wants to ask questions about the video. Supports multi-turn questioning: open the panel once, ask multiple questions. Triggers on: "YouTube ์์์ ๋ํด ์ง๋ฌธํด์ค" + URL, "์ด ์ ํ๋ธ ์์ ์์ฝํด์ค" + URL, "/ask-yt [URL] [question]", User wants to query YouTube's Ask/์ง๋ฌธํ๊ธฐ built-in AI feature |
โ ๏ธ Language Policy
- Output to user: KOREAN by default
- Phase instructions: ENGLISH (mandatory)
Available MCP Tools
| Tool | Purpose |
|---|
mcp__plugin_ask-yt_yt__open_ask_panel | Navigate to video URL and open the Ask panel (call once per video) |
mcp__plugin_ask-yt_yt__ask_video | Ask a question in the open panel (call multiple times) |
mcp__plugin_ask-yt_yt__close_session | Close the Playwright session when done |
Phase 0: Chrome CDP Auto-Setup (Automated Fallback)
Trigger this phase automatically when:
open_ask_panel returns a Chrome connection error, OR
- Starting the skill for the first time
Do NOT ask the user to run commands manually. Execute each step using Bash, and only pause to ask the user for decisions.
Step 0-1: Check if CDP is already running
curl -s http://localhost:9222/json/version 2>/dev/null | python3 -c \
"import sys,json; d=json.load(sys.stdin); print('connected:', d['Browser'])" 2>/dev/null \
|| echo "not_connected"
- If
connected: โ CDP is already running. Skip to Phase 2.
- If
not_connected โ proceed to Step 0-2.
Step 0-2: List available Chrome profiles (run silently, present result to user)
python3 -c "
import json, os
base = os.path.expanduser('~/Library/Application Support/Google/Chrome')
profiles = []
for name in sorted(os.listdir(base)):
pref = os.path.join(base, name, 'Preferences')
if os.path.isfile(pref):
try:
d = json.load(open(pref))
email = (d.get('account_info') or [{}])[0].get('email', '(์์)')
profiles.append((name, email))
print(f'{name}: {email}')
except: pass
"
Present the profile list to the user and ask which to use via AskUserQuestion (one option per profile).
Default to the profile that looks like their main YouTube account.
Step 0-3: Ask permission to kill Chrome and set up CDP
Use AskUserQuestion to confirm:
- "Chrome์ ์ข
๋ฃํ๊ณ CDP ๋ชจ๋๋ก ์ฌ์์ํ ๊น์?"
- Options: "๋ค, ์งํํด์ฃผ์ธ์" / "์๋์, ์๋์ผ๋ก ํ ๊ฒ์"
If user declines โ provide manual instructions and stop.
Step 0-4: Kill Chrome
pkill -9 -f "Google Chrome" 2>/dev/null; sleep 1; echo "์ข
๋ฃ ์๋ฃ"
Step 0-5: Check if Chrome-CDP directory already exists, ask whether to re-copy
PROFILE="<selected_profile>"
CDP_DIR="$HOME/Library/Application Support/Google/Chrome-CDP"
if [ -d "$CDP_DIR/$PROFILE" ]; then
echo "exists"
else
echo "not_exists"
fi
- If
exists โ Use AskUserQuestion:
- "๊ธฐ์กด Chrome-CDP ํ๋กํ์ด ์์ต๋๋ค. ์ฌ์ฌ์ฉํ ๊น์, ์๋๋ฉด ์ต์ ํ๋กํ๋ก ๋ค์ ๋ณต์ฌํ ๊น์?"
- Options: "์ฌ์ฌ์ฉ (๋น ๋ฆ)" / "๋ค์ ๋ณต์ฌ (์ต์ ์ฟ ํคยท์ธ์
๋ฐ์)"
- If
not_exists โ proceed to copy automatically.
Step 0-6: Copy profile (if needed)
PROFILE="<selected_profile>"
SRC="$HOME/Library/Application Support/Google/Chrome/$PROFILE"
DST="$HOME/Library/Application Support/Google/Chrome-CDP"
rm -rf "$DST/$PROFILE"
mkdir -p "$DST"
cp -r "$SRC" "$DST/$PROFILE"
cp "$HOME/Library/Application Support/Google/Chrome/Local State" "$DST/" 2>/dev/null
rm -f "$DST/$PROFILE/LOCK"
echo "๋ณต์ฌ ์๋ฃ"
Step 0-7: Launch Chrome with CDP in background
PROFILE="<selected_profile>"
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 \
--user-data-dir="$HOME/Library/Application Support/Google/Chrome-CDP" \
--profile-directory="$PROFILE" \
--no-first-run \
2>/dev/null &
echo "Chrome ์์๋จ (PID: $!)"
Step 0-8: Verify CDP connection (retry loop, up to 10 attempts)
for i in $(seq 1 10); do
RESULT=$(curl -s http://localhost:9222/json/version 2>/dev/null | python3 -c \
"import sys,json; d=json.load(sys.stdin); print(d['Browser'])" 2>/dev/null)
if [ -n "$RESULT" ]; then
echo "โ
CDP ์ฐ๊ฒฐ ์ฑ๊ณต: $RESULT"
break
fi
echo "โณ ์ฐ๊ฒฐ ๋๊ธฐ ์ค... ($i/10)"
sleep 1
done
if [ -z "$RESULT" ]; then
echo "โ CDP ์ฐ๊ฒฐ ์คํจ"
fi
- On success โ proceed to Phase 2.
- On failure after 10 attempts โ report error to user with the common errors table below.
Common Errors
| Error | Cause | Fix |
|---|
| CDP ์ฐ๊ฒฐ ์คํจ (10ํ ์๋) | Chrome์ด ์์ง ์์๋์ง ์์ | ์ ์ ํ ์ฌ์๋ ๋๋ Step 0-4๋ถํฐ ๋ฐ๋ณต |
| Profile selection screen appears | ํ๋กํ ์ด๋ฆ ๋ถ์ผ์น | Step 0-2์์ ์ ํํ ๋๋ ํ ๋ฆฌ ์ด๋ฆ ํ์ธ |
์ง๋ฌธํ๊ธฐ button not found | YouTube ๋ก๊ทธ์ธ ์ ๋จ | CDP Chrome์์ youtube.com์ ์ง์ ๋ก๊ทธ์ธ |
Ask ๊ธฐ๋ฅ์ด ์ง์๋์ง ์์ต๋๋ค | ํด๋น ์์ ๋ฏธ์ง์ | ๋ค๋ฅธ ์์์ผ๋ก ์๋ (๋ผ์ด๋ธ ์คํธ๋ฆผ ๋ฑ ๋ถ๊ฐ) |
Phase 1: Input Collection
Collect the following from the user:
- YouTube URL โ must be
https://www.youtube.com/watch?v=...
- Question(s) โ what to ask the YouTube AI
If either is missing, use AskUserQuestion.
Phase 2: Open Panel
Call mcp__plugin_ask-yt_yt__open_ask_panel once per video:
tool: mcp__plugin_ask-yt_yt__open_ask_panel
args:
url: <YouTube URL>
cdp_port: 9222 (๊ธฐ๋ณธ๊ฐ)
timeout_ms: 30000 (๊ธฐ๋ณธ๊ฐ)
On connection error โ immediately run Phase 0 (automated setup), then retry open_ask_panel.
After successful open_ask_panel, initialize the JSONL log file using Bash:
python3 -c "
import re, json, sys
url = sys.argv[1]
video_id = re.search(r'[?&]v=([^&]+)', url).group(1)
filename = f'YT_{video_id}_raw.jsonl'
open(filename, 'w').close() # truncate/create fresh
print(filename)
" "<YouTube URL>"
Save the returned filename (e.g. YT_EQ-Rnx-k-Ec_raw.jsonl) โ use it in every Phase 4 append step.
Phase 3: Complete Video Dissection
Goal: Ask enough questions that someone who reads the final document does NOT need to watch the video. Cover every section, every claim, every example, every demo.
Target: 25โ30 questions total. Run autonomously without waiting for user input.
Step 3-1: Structure Mapping (ALWAYS ask these 2 first)
Q1 โ Full outline:
์ด ์์์ ์ ์ฒด ๋ชฉ์ฐจ๋ฅผ ํ์์คํฌํ์ ํจ๊ป ์๋ ค์ค.
์ฃผ์ ์น์
, ์์ฃผ์ , ๊ฐ ์น์
์์ ๋ค๋ฃจ๋ ํต์ฌ ๋ด์ฉ์ ๋น ์ง์์ด ์ ๋ฆฌํด์ค.
Q2 โ Speaker & context:
๋ฐํ์๋ ๋๊ตฌ์ด๊ณ , ์ด ๋ฐํ์ ๋ฐฐ๊ฒฝ(ํ์ฌ๋ช
, ๊ฐ์ต ๋งฅ๋ฝ, ์ฒญ์ค)์ ๋ฌด์์ธ์ง ์๋ ค์ค.
๋ฐํ์์ ์ ๋ฌธ์ฑ๊ณผ ์ด ๋ฐํ๋ฅผ ํ๊ฒ ๋ ๊ณ๊ธฐ๋ ํฌํจํด์ค.
Step 3-2: Section-by-Section Excavation
From the outline in Q1, identify every major section. For EACH section, ask ALL of the following sub-questions (adapt wording to use exact section names):
Sub-question A โ Verbatim detail:
[์น์
๋ช
] ๋ถ๋ถ์์ ๋ฐํ์๊ฐ ์ ํํ ์ด๋ค ๋ง์ ํ๋์ง ์ต๋ํ ์์ธํ ์๋ ค์ค.
๊ตฌ์ฒด์ ์ธ ๋ฐ์ธ, ์์, ๋น์ , ์คํ ๋ฆฌ๋ฅผ ๋ชจ๋ ํฌํจํด์ ์ค๋ช
ํด์ค.
Sub-question B โ Data & evidence:
[์น์
๋ช
]์์ ์ธ๊ธ๋ ๊ตฌ์ฒด์ ์ธ ์์น, ํต๊ณ, ์ฌ๋ก, ์คํ ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด ์ ๋ถ ์๋ ค์ค.
Sub-question C โ Demos & visuals (if applicable):
[์น์
๋ช
]์์ ํ๋ฉด์ ๋ณด์ฌ์ค ์์ฐ, ์ฝ๋, ๋ค์ด์ด๊ทธ๋จ, ๋๋ ์ค์๊ฐ ๋ฐ๋ชจ๊ฐ ์์์ผ๋ฉด ์ค๋ช
ํด์ค.
Skip Sub-question C if the section clearly has no demo/visual component.
Step 3-3: Cross-Cutting Deep Dives
After all sections are covered, ask these regardless of topic:
Terminology sweep:
์ด ์์์์ ๋ฐํ์๊ฐ ์๋กญ๊ฒ ์ ์ํ๊ฑฐ๋ ๋
ํนํ๊ฒ ์ฌ์ฉํ ์ฉ์ด๋ ๊ฐ๋
์ด ์์ด?
๊ฐ๊ฐ ๋ฐํ์์ ์ ์๋ฅผ ๊ทธ๋๋ก ์ค๋ช
ํด์ค.
Most controversial claim:
์ด ์์์์ ๊ฐ์ฅ ๋
ผ์์ ์ด๊ฑฐ๋ ๋ฐ์ง๊ด์ ์ธ ์ฃผ์ฅ์ ๋ฌด์์ด๊ณ ,
๋ฐํ์๋ ๊ทธ ๊ทผ๊ฑฐ๋ก ๋ฌด์์ ์ ์ํ์ด?
Audience Q&A (if exists):
๋ฐํ ํ ์ฒญ์ค ์ง๋ฌธ์ด๋ Q&A ์ธ์
์ด ์์์ด? ์์๋ค๋ฉด ์ด๋ค ์ง๋ฌธ๊ณผ ๋ต๋ณ์ด ์ค๊ฐ๋์ง ์๋ ค์ค.
Completeness check:
์ง๊ธ๊น์ง ๋ด๊ฐ ๋ฌป์ง ์์ ์ค์ํ ๋ด์ฉ์ด ์ด ์์์ ๋จ์ ์์ด?
์๋ค๋ฉด ๋ฌด์์ธ์ง ์๋ ค์ค.
Step 3-4: Chain Follow-ups (run after EVERY answer throughout)
After each answer, scan for these and immediately ask if found:
| Trigger | Follow-up pattern |
|---|
| Named tool/product/company | "[name]"์ด ๊ตฌ์ฒด์ ์ผ๋ก ๋ฌด์์ธ์ง, ์ด๋ป๊ฒ ์๋ํ๋์ง ์ค๋ช
ํด์ค |
| Number/stat without context | "[stat]"์ด๋ผ๋ ์์น์ ์ถ์ฒ์ ์๋ฏธ๋ฅผ ๋ ์์ธํ ์ค๋ช
ํด์ค |
| "~ํ๋ฉด ๋๋ค" without how | "[claim]"์ ์ค์ ๋ก ์ด๋ป๊ฒ ํ๋์ง ๋จ๊ณ๋ณ๋ก ์ค๋ช
ํด์ค |
| Comparison A vs B | [A]์ [B]์ ์ฐจ์ด๋ฅผ ๋ ๊ตฌ์ฒด์ ์ผ๋ก ์ค๋ช
ํด์ค. ์ธ์ ์ด๋ค ๊ฑธ ์ ํํด์ผ ํด? |
| Failure/risk mentioned | [failure case]๊ฐ ์ค์ ๋ก ๋ฐ์ํ ์ฌ๋ก๋ ๊ทธ ์์ธ์ ๋ ์์ธํ ์ค๋ช
ํด์ค |
| Chips signal new topic | Use the chip text as the basis for a targeted question |
Rules:
- Use EXACT quotes and terms from the previous answer โ never ask generically
- Never re-ask something already answered
- Chain follow-ups take priority over moving to the next section if an answer raises something significant
Step 3-5: Termination
Stop when:
- All sections from the outline are excavated AND cross-cutting questions are done, OR
- Hard limit: 30 questions
On termination โ call close_session โ proceed to Phase 5.
Phase 4: Display, Append & Loop
After each ask_video call:
Step 4-1: Show answer to user
**[Q{n}]** {question}
{answer}
Step 4-2: Append to JSONL immediately
Run this Bash command right after displaying the answer (replace {n}, {question}, {answer}, {chips_json}, {jsonl_file} with actual values):
python3 - <<'PYEOF'
import json
entry = {
"q_num": {n},
"question": {question_as_json_string},
"answer": {answer_as_json_string},
"chips": {chips_as_json_array}
}
with open("{jsonl_file}", "a", encoding="utf-8") as f:
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
print(f"Q{n} ์ ์ฅ ์๋ฃ")
PYEOF
{question_as_json_string}: the question string wrapped in json.dumps() style (properly escaped)
{answer_as_json_string}: the answer string properly escaped
{jsonl_file}: the filename initialized in Phase 2
Step 4-3: Loop
Immediately return to Phase 3 (Step 3-2 or 3-4) to determine the next question. Do NOT wait for user input. Keep the chain running autonomously until the termination condition.
Phase 5: Generate Complete Video Report
After closing the session, read the JSONL log and write a document comprehensive enough to fully replace watching the video.
Step 5-1: Read all Q&A from JSONL
python3 -c "
import json
with open('{jsonl_file}', encoding='utf-8') as f:
entries = [json.loads(line) for line in f if line.strip()]
print(f'์ด {len(entries)}๊ฐ Q&A ๋ก๋๋จ')
for e in entries:
print(f\"Q{e['q_num']}: {e['question'][:60]}...\")
"
Verify all entries are present. If any are missing, re-ask those questions via ask_video and append manually.
Step 5-2: Determine report filename
python3 -c "
import re, sys
url = sys.argv[1]
video_id = re.search(r'[?&]v=([^&]+)', url).group(1)
print(f'YT_{video_id}_REPORT.md')
" "<YouTube URL>"
Step 5-3: Write the document
Use the Write tool to create {report_filename} in the current working directory. Use ALL entries from the JSONL โ never truncate or summarize Q&A content.
๋ฌธ์ ํ์:
# {์์ ์ ๋ชฉ} โ ์์ ํด์ค
> **์์**: {url}
> **๋ฐํ์**: {speaker name & title}
> **ํ์ฌ**: {event name & date if known}
> **์์ฑ์ผ**: {YYYY-MM-DD}
> **๋ถ์ ์ง๋ฌธ ์**: {n}๊ฐ
---
## ํ๋์ ๋ณด๊ธฐ (Executive Summary)
{์์ ์ ์ฒด๋ฅผ 3-5 ๋จ๋ฝ์ผ๋ก ์์ถ. ๋ฐํ์ ํต์ฌ ์ฃผ์ฅ, ๊ทผ๊ฑฐ, ๊ฒฐ๋ก ์ ํฌํจ.
์ด ์น์
๋ง ์ฝ์ด๋ ๋ฐํ์ 80%๋ฅผ ํ์
ํ ์ ์์ด์ผ ํจ.}
---
## ๋ชฉ์ฐจ
{Q1์์ ์ป์ ํ์์คํฌํ ๊ธฐ๋ฐ ๋ชฉ์ฐจ๋ฅผ ๊ทธ๋๋ก ์ฌํ}
---
## ๋ฐํ์ & ๋ฐฐ๊ฒฝ
{Q2 ๋ด์ฉ. ๋ฐํ์ ์๊ฐ, ํ์ฌ ๋งฅ๋ฝ, ๋ฐํ ๋๊ธฐ}
---
## ์น์
๋ณ ์์ธ ํด์ค
### 1. {์น์
๋ช
} ({timestamp ๋ฒ์})
{ํด๋น ์น์
์ Sub-question A~C ๋ต๋ณ์ ํตํฉํ์ฌ ์์ .
๋ฐํ์์ ๋ฐ์ธ์ ์ต๋ํ ์ฌํํ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ๊ตฌ์กฐํ.
๊ตฌ์ฒด์ ์์น, ์์, ๋น์ ๋ฅผ ๋ชจ๋ ํฌํจ.
๋ฐ๋ชจ๊ฐ ์์์ผ๋ฉด "[์์ฐ]" ๋ธ๋ก์ผ๋ก ํ์.}
> **[์์ฐ]** {๋ฐ๋ชจ ๋ด์ฉ ์ค๋ช
}
### 2. {์น์
๋ช
} ({timestamp ๋ฒ์})
{...}
(๋ชจ๋ ์น์
๋น ์ง์์ด ํฌํจ)
---
## ํต์ฌ ์ฉ์ด ์ฌ์
| ์ฉ์ด | ๋ฐํ์์ ์ ์ |
|------|-------------|
| {term 1} | {definition} |
| {term 2} | {definition} |
---
## ๊ฐ์ฅ ๋
ผ์์ ์ธ ์ฃผ์ฅ
> **์ฃผ์ฅ**: {controversial claim ์๋ฌธ}
**๋ฐํ์์ ๊ทผ๊ฑฐ:**
{evidence provided}
**๋นํ์ ๊ณ ๋ ค:**
{limitations or counterpoints surfaced during questioning}
---
## Q&A ์ธ์
์์ฝ
{์ฒญ์ค ์ง๋ฌธ์ด ์์์ผ๋ฉด Q&A ํ์์ผ๋ก ์ฌํ. ์์ผ๋ฉด ์ด ์น์
์๋ต.}
---
## ์ค์ ์ ์ฉ ๊ฐ์ด๋
### ์ฆ์ ์คํ (์ค๋๋ถํฐ)
- {์ก์
1}
- {์ก์
2}
- {์ก์
3}
### ์ค๊ธฐ ๋ณํ (1-6๊ฐ์)
- {๋ณํ 1}
- {๋ณํ 2}
### ํฐ ๋ฐฉํฅ์ฑ (์ฅ๊ธฐ)
- {๋ฐฉํฅ 1}
---
## ํต์ฌ ๋ช
์ธ
> "{exact quote 1}" โ {speaker}
> "{exact quote 2}" โ {speaker}
---
## ๋จ์ ์ง๋ฌธ๋ค
{์์์์ ๋ค๋ฃจ์ง ์์๊ฑฐ๋ ๋ตํ์ง ์์ ์ค์ํ ์ง๋ฌธ๋ค. ์์ฒญ์๊ฐ ์ถ๊ฐ๋ก ํ๊ตฌํ ์ฃผ์ .}
Rules:
- ์น์
๋ณ ์์ธ ํด์ค: ๋ฐํ์์ ์ค์ ๋ฐ์ธ์ ์ต๋ํ ์ฌํ โ ์์ฝ์ด ์๋๋ผ ์ฌํ
- ์์นยท์ฌ๋กยท๋น์ ์ ๋ถ ํฌํจ, ์ ๋ ์๋ตํ์ง ๋ง ๊ฒ
- Chip ์ ์์ ๋ฌธ์์ ํฌํจํ์ง ์์ (UI artifact)
- ์ง๋ฌธ์ด 3๊ฐ ๋ฏธ๋ง์ด๋ฉด ์ด ํฌ๋งท ๋์ ๋จ์ Q&A ๋์ด๋ก ๋์ฒด
Step 5-3: Notify user
Tell the user: ๐ ์์ ์์ ํด์ค ๋ฌธ์๊ฐ ์ ์ฅ๋์์ต๋๋ค: {filename}