Notes skill
Skill speech115/notes-skill
Local-first /notes skill for agent-made study notes from YouTube, transcripts, audio, and video
npx -y skills add speech115/notes-skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Create detailed study notes from YouTube videos, local media, or local transcripts. Use only when the user explicitly asks to make notes/a конспект through notes, names the notes skill, or runs /notes. Do not use for ordinary summaries, YouTube links, or конспект requests that do not explicitly mention notes.
SKILL.md
14.6 KB, ~3.4k tokens by cl100k_base, as published. Nobody here has run it
/notes — detailed study notes
Triggers only when the user directly asks to use notes for notes/конспект, names the notes skill, or explicitly runs /notes ....
Do not activate this skill for ordinary summary requests, bare YouTube URLs, or generic сделай конспект / законспектируй requests unless the user explicitly says to use notes.
This is a local agent skill, not an app project.
Treat notes-runner as the source of truth for:
- input routing
- stage routing
- note contract
- final quality / contract validation
Use the bundled helper:
<skill-root>/scripts/notes-runner
Do not assume a global notes-runner exists in PATH.
Supported inputs
Starter mode (no extra setup):
- a YouTube URL with usable subtitles/autosubs
- a local absolute path to
.mdor.txt
With audio transcription setup (MacWhisper Parakeet or Groq API):
- audio/video files (
.m4a,.mp3,.wav,.ogg,.opus,.mp4,.mov,.mkv,.webm,.avi) - a directory of audio/text files for batch prepare/index mode
Advanced setup:
- Telegram voice/audio
- YouTube videos without usable subtitles
- speaker diarization
If the user provides an audio/video file but transcription is not available, explain the setup and point to:
<skill-root>/ADVANCED.md
First run
If the user looks confused or asks how to start, tell them to try:
What skills are available?
/notes https://www.youtube.com/watch?v=...
/notes /absolute/path/to/file.md
/notes /path/to/audio.mp3
/notes /path/to/video.mp4
Input routing
If no argument was provided:
- Ask for exactly one input:
- one YouTube URL, or
- one absolute path to
.md/.txt
- Do not start processing until the user gives it.
If the argument is a YouTube URL:
<skill-root>/scripts/notes-runner youtube "$ARGUMENTS" --prepare --json
If the argument is an absolute path to .md or .txt:
<skill-root>/scripts/notes-runner local "$ARGUMENTS" --prepare --json
If the argument is an absolute path to an audio or video file (.m4a, .mp3, .wav, .ogg, .opus, .mp4, .mov, .mkv, .webm, .avi):
<skill-root>/scripts/notes-runner audio "$ARGUMENTS" --prepare --json
Use --title "Custom Title" when the filename is not a good title.
Use --language to set the transcription language (default: ru). Only add --language en for English content.
Use --transcribe-backend parakeet --parakeet-benchmark only when you need timing telemetry for the local MacWhisper Parakeet path.
If the argument is a directory containing multiple files:
<skill-root>/scripts/notes-runner batch "$ARGUMENTS" --prepare --json
Batch JSON is not a single-note payload. Do not apply the single-note continuation flow below to the whole batch result.
For batch mode:
- Report the batch
results,index,ok, andfailedvalues. - Do not claim final notes, final HTML, or Telegram delivery unless the runner result explicitly includes those final artifacts for each item.
- If the user wants one batch item completed end-to-end, run
/noteson that specific source file or resume that item's$WORK_DIRthrough the single-note flow.
If the argument is not recognized, ask the user to provide one of:
- a YouTube URL
- an absolute path to
.md/.txt - an absolute path to an audio/video file
- a directory for batch prepare/index processing
Error handling
If notes-runner exits with non-zero or produces no JSON output, report the error to the user and STOP. Do not proceed to extraction with missing/empty data.
After the helper runs
This section applies only to single-note commands (youtube, local, audio, telegram) that return one bundle_dir and one prepare.work_dir.
For batch, stop at the batch summary unless the runner exposes per-item final artifacts or the user chooses a specific item to finish.
Read the JSON output and extract these variables:
| Variable | JSON path | Description |
|---|---|---|
$BUNDLE_DIR | bundle_dir | Output folder with final files |
$RAW_TITLE | title | Original title from source (filename, video title) |
$TRANSCRIPT_PATH | transcript_path | Path to transcript file |
$WORK_DIR | prepare.work_dir | Temp working directory for intermediate agent files |
$SUGGESTED_MD | suggested_output_md | Default markdown output path |
$SUGGESTED_HTML | suggested_output_html | Default HTML output path |
$TOTAL_CHUNKS | prepare.total_chunks | Number of chunks (determines single vs multi-agent) |
$SPEAKER_STAGE | prepare.stage_hints.speaker_identification | "skip" or "identify" — whether to run speaker ID |
$STATUS | status | Current work-dir stage/chunk status from notes-runner |
$EXECUTION_PLAN | execution_plan | Runner-provided orchestration plan for resume/single/micro-multi/multi-stage execution |
$PREPARE_REUSED | prepare.reused | true when notes-runner reused an existing work dir |
$WARNINGS | warnings | Array of warning strings (may be empty) |
Key distinction: $BUNDLE_DIR is the permanent output folder. $WORK_DIR is a temp directory inside it where agents write intermediate files (blocks, manifests, summaries).
IMPORTANT: Do NOT read the transcript into main context. The extraction agents read it themselves. Reading it here wastes ~2K+ tokens. Only read prescan_context.txt in main context.
One-shot contract
This one-shot contract applies to one source item at a time. It does not turn the current batch summary payload into a single note.
- Do not stop after
--preparesucceeds. - Continue autonomously through extraction, header, and assemble until the final note files exist or a real error stops the run.
- Do not ask the user to manually run extraction,
replace-speakers,build-tldr, orassemble. - If worker agents are needed for extraction, launch them yourself, wait for them, validate their outputs, and keep going.
- Only report the final note paths or a real blocking error.
Processing flow
Goal: keep /notes deterministic. Prefer the runner state over ad-hoc decisions.
Core rules
- Do not rerun
youtube/local/audio ... --prepareafter it already succeeded unless the user explicitly asked for refresh. - Do not read the full transcript into main context.
- If the helper succeeded and
transcript_pathexists,warningsare informational. Continue unless the helper itself exited non-zero. - Prefer
$EXECUTION_PLAN,$STATUS,note-contract.json, andquality-checks.jsonover any hand-written heuristics in the skill. - If
$PREPARE_REUSED == true, assume this is a resume/continue path and skip any stage already marked ready in$STATUS. - Valid YouTube transcript sources are:
existing,youtube-transcript-api,subtitles,api.apimeans the slower audio fallback ran; it is not an error by itself. - Do not use
ToolSearchormcp__telegram__send_filehere. Telegram is best-effort insideassembleonly. - Prefer richer coverage over aggressive compression for long-form material. A 90-180 minute source should usually produce many local blocks, not a handful of mega-blocks.
- Treat runner-provided density requirements as hard constraints. If the extraction prompt says the chunk must yield at least
Nblocks, do not collapse it further. - If assemble reports that the note is too compressed for source duration, treat that as a real contract failure and expand the coverage instead of polishing wording.
- For
120+minute sources, default to a deep-longform reading mode: preserve intermediate conclusions, participant situations, and concrete examples instead of flattening them into generic theses.
Read only required files
After prepare:
- Prefer runner-generated prompt packs from
$EXECUTION_PLAN.prompt_packs. - Read
$WORK_DIR/prescan_context.txt. - Read
$WORK_DIR/header-seed.jsonand$WORK_DIR/note-contract.jsonbefore writingheader.md. - Read block templates from
<skill-root>/block-templates/only if the prompt pack files are missing.
Extraction routing
Use $EXECUTION_PLAN.mode and *.should_run flags as the source of truth for routing. Do not invent extra stages.
If $EXECUTION_PLAN.mode == "single" and $EXECUTION_PLAN.extraction.should_run == true: use single-agent mode.
Launch one worker agent using the runner-generated extraction prompt from $EXECUTION_PLAN.prompt_packs.extract.A (or the only chunk entry in chunks_to_extract). The agent must:
- read the transcript file itself
- write
chunk_A_block_*.md,manifest_chunk_A.tsv,summary_chunk_A.md - also write
$WORK_DIR/tldr.md - write the extraction sentinel JSON requested by the prompt pack
Then skip the TL;DR wave and continue to title/header + assemble.
If $EXECUTION_PLAN.extraction.should_run == false, do not relaunch extraction. Reuse the existing block files and continue from the first missing stage.
If $EXECUTION_PLAN.mode == "micro-multi" or $EXECUTION_PLAN.mode == "multi": use parallel chunk mode.
- If
$EXECUTION_PLAN.speaker_identification.should_run == true, launch one speaker-ID agent using$EXECUTION_PLAN.prompt_packs.speaker_identification. - Launch one extraction agent per chunk from
$EXECUTION_PLAN.extraction.chunks_to_extract.- Use the runner-generated prompt file from
$EXECUTION_PLAN.prompt_packs.extract[chunk_id]. - Keep
Speaker Nlabels untilreplace-speakers. - Each chunk must write
chunk_[id]_block_*.md,manifest_chunk_[id].tsv,summary_chunk_[id].md. - Each chunk must also write the extraction sentinel JSON described in its prompt pack.
- Do not relaunch chunks outside
chunks_to_extract.
- Use the runner-generated prompt file from
- Wait for all extraction work to finish.
- Validate every chunk: at least one
chunk_[id]_block_*.mdand onemanifest_chunk_[id].tsvmust exist. If any chunk is missing output, stop and report the failure. - Run:
<skill-root>/scripts/notes-runner replace-speakers "$WORK_DIR"
- If
$EXECUTION_PLAN.tldr.should_run == trueand$EXECUTION_PLAN.tldr.strategy == "deterministic-merge", run:
<skill-root>/scripts/notes-runner build-tldr "$WORK_DIR" --json
- If
$EXECUTION_PLAN.tldr.should_run == trueand$EXECUTION_PLAN.tldr.strategy == "agent", launch one TL;DR agent using$EXECUTION_PLAN.prompt_packs.tldr_agent. - If
$EXECUTION_PLAN.replace_speakers.after_tldr == true, runreplace-speakersonce more after TL;DR completes sotldr.mdis also cleaned.
Title + header
- If
$EXECUTION_PLAN.title_header.should_run == true, run the deterministic header builder first:
<skill-root>/scripts/notes-runner build-header "$WORK_DIR" --json
Use manual header generation only if build-header fails, returns no title/header path, or the user explicitly requires a custom title.
2. Read speakers.txt if it exists, plus prescan_context.txt, plus $EXECUTION_PLAN.title_header.header_seed_path only when manual fallback is needed.
3. Respect $EXECUTION_PLAN.content_mode and $EXECUTION_PLAN.contract; do not improvise a different note schema.
4. Generate title ($FINAL_TITLE) from the build-header JSON title when available. In manual fallback, use [Speaker] — [Core Topic].
- Example:
Роман — Тело, энергия и продуктивность - If
$EXECUTION_PLAN.title_header.author_hintorspeaker_candidatesnames a likely YouTube author/uploader and the material is single-speaker, use that real name as[Speaker]. - No clear speaker name:
[Topic] (групповая сессия) - Single unnamed YouTube speaker with no usable author hint: use a descriptive topic title, not
Speaker 1 - Prefer
$EXECUTION_PLAN.title_header.title_candidatesbefore inventing a fresh title from scratch.
- Set:
$OUTPUT_MD→$BUNDLE_DIR/$FINAL_TITLE.md$OUTPUT_HTML→$BUNDLE_DIR/$FINAL_TITLE.html
- In manual fallback, write
$WORK_DIR/header.mdusing the runner-generated header prompt or the header template.- Preserve deterministic metadata lines from
header-seed.json/note-contract.json. - Generate only the abstract and
Главная рамка автора.
- Preserve deterministic metadata lines from
Assemble
Run exactly once when $EXECUTION_PLAN.assemble.should_run == true:
<skill-root>/scripts/notes-runner assemble \
"$WORK_DIR" \
"$OUTPUT_MD" \
"$OUTPUT_HTML" \
"$FINAL_TITLE" \
--json
The assemble step generates the appendix deterministically from manifests.
If assemble exits non-zero or returns contract_errors, inspect the failure before giving up.
For fixable note-quality failures, repair the upstream files you control and rerun assemble.
Do this repair loop up to 2 times.
Typical fixable failures:
- actionability too weak -> strengthen
action_now,action_check,action_avoid, and practical wording in blocks/summaries - note too compressed for duration -> expand block coverage instead of polishing prose
- weak appendix/action plan -> improve manifest action fields and rerun assemble
- missing header contract fields -> fix
header.mdand rerun
Only stop immediately for real blockers:
- helper command exits non-zero before artifacts exist
- required source files are missing
- a chunk agent failed to produce required files
- the contract error points to missing source evidence you cannot invent honestly
Telegram delivery is part of the normal /notes completion contract.
- If the user did not explicitly ask to skip Telegram, do not treat
telegram_delivery.success == falseas a minor warning. - Retry
assemblewith Telegram enabled when the current run was a smoke/debug path such as--skip-telegram. - If Telegram delivery still fails on the real run, stop and report it as a blocking error together with the note paths and the delivery failure reason.
- Use
--skip-telegramonly for explicit debug/smoke work, never as the final completion path for a user-facing/notesrequest.
Output to the user
At the end, report only the practical result:
- markdown path
- HTML path
- whether Telegram delivery succeeded
- whether there were warnings
Be concise.
Do not paste the generated notes into chat when files were already written successfully. Do not stop earlier with an internal stage update when the run can still continue autonomously.