Notes you can actually learn from — not a transcript dump, not a one-paragraph summary.
Point it at a video, an article, a paper, a slide deck, or a repo — or at
several at once, and they fold into one note. You get a self-contained
HTML page shaped to what the source is — an argument gets a summary, the one
takeaway, key points and an outline; a catalogue of tools gets a matrix and a
card per tool; a recipe gets a ticket, the ingredients and the method — written
to ~/take-notes/html_reports/ and opened in your browser. They pile up into a browsable archive you own, on your disk, in
plain HTML that will still open in ten years.
|
|
|
Why I built it · How to use · Install · Gallery · Credits
I kept watching hour-long videos and reading long posts, feeling like I'd learned something, and then having nothing to show for it a week later. The summaries I could get were either a wall of transcript or three bland sentences — both useless for actually remembering anything.
So the rule this skill follows is: explain, don't compress. A bullet only someone who already watched the video would understand has failed. Order things by what has to be understood first, not by when they were said. Say what the source left unanswered. And keep every note as one HTML file on my own disk, because notes that live in someone else's product stop being yours eventually.
Point it at a URL. That is the whole thing:
/take-notes https://www.youtube.com/watch?v=NiKtZgImBdY
/take-notes https://simonwillison.net/2025/Jan/11/phi-4-bug-fixes/
/take-notes https://arxiv.org/abs/2407.09141
/take-notes https://docs.google.com/presentation/d/1hcGZ4U9TjZZzcGNbH2K6wYD45qwZTyo_gosCQsnHlnc/edit
/take-notes https://github.com/ggml-org/llama.cppIt writes ~/take-notes/html_reports/YYYY-MM-DD-<slug>.html and opens it.
Re-running on the same source the same day updates that note rather than
leaving a near-duplicate beside it.
It runs only when you ask. The skill never fires on a URL you merely mention in conversation, in any tool it's installed in.
| YouTube | any video URL, including the many non-YouTube sites yt-dlp supports |
| Local media | video or audio already on disk |
| Web articles | blog posts, docs pages, news articles |
| arXiv papers | full text via arXiv's HTML rendering, not just the abstract |
| Google Slides | slide text plus the speaker notes, and the deck's diagrams as figures |
| GitHub repos | an orientation note: what it does, how it's laid out, what to read first |
Pass more than one URL and they combine into a single note — a talk and the deck it was given from, a paper and the repo that implements it:
/take-notes https://youtu.be/rNgUoH7Wbv8 https://docs.google.com/presentation/d/1hcGZ…/editAny mix of the sources above works, and the note reads them against each other rather than stapling two summaries together: overlap is written once from whichever source explains it better, and the gaps are the point — the diagram that is on a slide and in no transcript, the number said out loud that is on no slide. Where the two disagree, the note says so.
The first URL is the primary source. It gives the note its title, byline and layout — lead with the video for the two-pane note with a poster and clickable timestamps, lead with the deck or the article for the reading layout. The rest are listed under the source link in the rail, and stay traceable inline: a point that came from slide 7 links to slide 7.
If a companion source can't be fetched, the note is still written from the rest and says what was missing. If the primary can't be, the run stops.
Add a phrase after the URL and the run narrows to it:
/take-notes https://unsloth.ai/docs/basics/dynamic-3.0-ggufs "just the v3.0 methodology"
/take-notes https://youtu.be/… "only the part about retrieval"Focus narrows two things at once: what gets fetched — only the sections in scope are pulled in rather than the whole document, which is where the token saving comes from, since the source text is by far the largest input in a run — and what the finished notes emphasise. It pays on a docs page that stacks several versions of itself, a paper where you want one section, or a two-hour video where twenty minutes matter; a short single-topic post has nothing to trim. Leave it off to cover a source in full.
A theme is a palette and a typeface, not just colours. auto is the default
and the shipped behaviour: warm paper by day, graphite by night.
The same note, three themes. A theme changes the stock, the ink and the typeface; the composition never moves.
paper field blueprint graphite |
the house voice — Fraunces over Newsreader, on warm, green, blue and near-black stock |
bureau |
Swiss neutral, Space Grotesk, red signal accent |
acid |
highlighter green on near-black, Space Grotesk, hard 2px rules |
barbie |
Bodoni over Jost, hot pink, rounded corners |
petrol |
Jost throughout, cream and petrol — one typeface for everything |
notebook |
handwriting on ruled paper, blue biro, red correction pen |
/take-notes --theme # list them, marking the one in force
/take-notes --theme "notebook" # set it, write no noteThe gallery carries its own theme menu in the filter bar: it repaints at once, remembers your pick in that browser, and hands it to any note you open from a card — so an archive written in one theme reads in another. The config is the default baked into new notes; the menu is what you are reading in now. Neither rewrites notes already on disk.
A note's genre is the shape of its content — which sections it has and which template renders them. The skill picks it from what the source is, after reading it, so a cooking video and a conference talk come out as different objects rather than the same outline with different words:
| The source is… | Genre | You get |
|---|---|---|
| an argument — a talk, an article, a paper, a docs page, a repo | offprint |
the annotated offprint: summary, the one takeaway, key points, outline, concepts |
| several things of one kind on shared axes — tools, models, products, options | fieldguide |
a full-bleed masthead, a matrix, a card per thing with the same facets, a recommendation |
| a dish | recipe |
a ticket of facts, the ingredients pinned beside the method, numbered steps with times and settings |
The default is offprint, and it stays the default whenever the call is not
obvious — a wrong genre is worse than the plain one. Override it for a run with
--genre or in words ("write it as a recipe"); the skill says which genre it
chose whenever it is not the offprint. Each genre is one contract under
skills/take-notes/genres/ — a front-matter block
naming its layout and the "the source is…" line the router reads, then the
sections the skill writes — rendered by one of three layouts under assets/;
the colour theme applies to all of them.
Your own genres go in ~/take-notes/genres/<name>.md, in the same shape.
Pick a layout, write the sections, and it is routable the moment you give it a
when: line — or leave that out and use it by name with --genre <name>,
which is the safe way to try one. A file named like a bundled genre replaces
it: copy recipe.md there and change the facts on the card to have your own
recipe. uv run skills/take-notes/scripts/genres.py --list prints what is
installed, in the order the router reads it.
Optional — notes are written in English unless you say otherwise.
"ask" restores the per-run prompt, offering the source's own language first.
Override it for a single run with --lang, which beats the config — including
"ask", since an explicit flag is not a question:
/take-notes https://youtu.be/… --lang enPrecedence is --lang → a language named in words ("…in English") → config →
English. A missing or malformed config falls back to English rather than
failing, and an unsupported --lang is reported rather than silently applied.
When the source's language differs from the one used, the skill says so, so a
Spanish video never quietly becomes English notes without a word.
Every note is filed under one primary tag, plus any extras that apply. The
vocabulary lives beside language in the same config, and it is closed:
the skill picks from your list and never invents a tag, so the taxonomy stays
yours rather than whatever the model felt like that day.
// ~/take-notes/config.json
{ "language": "es", "tags": ["Unknown", "AI", "Investing", "Engineering"] }Nothing fits — or no vocabulary is set — and the note lands on Unknown,
silently. You are never prompted to invent a tag mid-run.
A tagged archive — the primary tag sits beside the kind on each card, and every tag in use gets a chip. The notes are the four real examples; the tags on them are illustrative.
The full grammar, for reference:
/take-notes <url> [more urls…] [focus] [--lang en|es] [--genre <name>]
/take-notes --tags | --add-tag "AI" | --remove-tag "AI" | --retag
/take-notes --theme | --theme "notebook"The second line manages tags instead of writing a note. Edit the list from the skill, or from the CLI when you're already in a terminal:
/take-notes --tags # list it
/take-notes --add-tag "AI" # add, report, write no note
/take-notes --remove-tag "AI" # remove
uv run skills/take-notes/scripts/tags.py --add AI --add Investing
uv run skills/take-notes/scripts/tags.py --remove InvestingBoth edit the same file and leave language untouched. Unknown is the
fallback the skill needs, so it can't be removed.
Set the vocabulary up after you'd already taken notes? /take-notes --retag
re-files the notes on disk against it, no source refetched and no prose
rewritten — it edits the tag row and nothing else:
/take-notes --retagIt reads each note's title and opening, picks from your vocabulary — never
outside it — and leaves anything that fits nothing on Unknown. Notes already
carrying a tag you chose are left alone. The underlying script is usable on its
own when you want to file one note by hand:
uv run skills/take-notes/scripts/retag.py --list # notes + current tags, as JSON
uv run skills/take-notes/scripts/retag.py --set NOTE.html --tag AI --tag EngineeringRebuild the gallery afterwards so the chips match. Changing a single note's tag
also still works the old way: re-run /take-notes on its source — same day,
same file, new tag.
Notes are yours, so they leave cleanly. Both exporters read the rendered notes; neither needs an agent or costs tokens.
uv run skills/take-notes/scripts/export.py --format md # → ~/take-notes/markdown/
uv run skills/take-notes/scripts/export.py --format anki # → ~/take-notes/take-notes.txtmd— one Markdown file per note with YAML frontmatter. Drop the folder into an Obsidian vault, or import it into Notion. Timestamp links survive as real Markdown links, and the note's tags land in the frontmattertags:list, which is what Obsidian's tag pane reads.anki— a tab-separated deck file. Cards come from Key points (claim → detail), Concepts (term → definition), and the one takeaway. The note's tags join the card kind in the tags column, so a deck filters by topic too. Import with File → Import and leave Allow HTML in fields on.
Works in any Agent Skills-compatible tool — Claude
Code, Codex, Cursor, OpenCode, Gemini CLI, and any other host that reads the
same standard SKILL.md — no per-tool variants to maintain. Every script is
stdlib-only Python run through uv; there is nothing to pip install.
Claude Code (auto-updates via the marketplace):
/plugin marketplace add davertor/take-notes
/plugin install take-notes@take-notes
That is the one to use if you have Claude Code — it is the only route that
auto-updates. The two options below are for everything else, or for editing the
skill yourself. Neither auto-updates; re-run it (or git pull) for the latest.
git clone https://github.com/davertor/take-notes
cd take-notes
./link-skill.sh # every tool
AGENT=claude ./link-skill.sh # one tool onlylink-skill.sh symlinks skills/take-notes into each
tool's skills directory (claude, codex, cursor, opencode, gemini,
agents). Idempotent, and replaces anything already occupying a target. A
real checkout — edit skills/take-notes/ directly, or git pull for
upstream changes.
Codex, Cursor, OpenCode, Gemini CLI, or any other Agent Skills host:
npx skills add davertor/take-notes -g # install for your user
npx skills add davertor/take-notes -g -a claude-code # one agent onlyPass -g — without it, add installs project-level into the current
folder instead of your user directories. Update with npx skills update take-notes.
| uv | runs the scripts; provisions its own Python, no separate install |
| yt-dlp + ffmpeg | video sources only — scripts/setup.py installs them via Homebrew on macOS |
| Whisper API key | optional, only for videos without captions — Groq or OpenAI, read from ~/.config/watch/.env |
Web articles need none of the above — that path uses the agent's fetch tool —
and Google Slides needs only uv: the deck reader is standard library, no API key.
Both install paths land on the same /take-notes — neither namespaces nor
renames it.
Notes pile up. scripts/gallery.py reads whatever is in
~/take-notes/html_reports/ and writes ~/take-notes/gallery.html — a card
per note, newest first, poster for videos and a filing plate for articles,
with a filter box (/ focuses it, Esc clears it). Then it opens it.
Under the filter bar is a chip per tag in use: click one to narrow the grid to that tag, click it again to clear. Chip and text filter combine.
The gallery — the four notes in docs/examples/, every one of them real output. Clone the repo and open any of them to see a note in full.
uv run ~/.claude/skills/take-notes/scripts/gallery.py # or your checkout pathWorth an alias, since you'll run it more than once:
alias notes='uv run ~/.claude/skills/take-notes/scripts/gallery.py'It's a plain script, not a skill — building an index of files on disk needs no model in the loop, so no agent is involved and nothing is spent. Re-run it after taking notes; it rebuilds from scratch every time, so a note you delete by hand simply stops appearing.
Flags: --no-open, --notes-dir, --out, --lang en|es (defaults to the
language in ~/take-notes/config.json).
Building the gallery also checks whether a newer version has been released, and
says so in the footer if your copy is behind — the clone and npx skills routes
don't auto-update, and a stale copy has no other symptom. It reads one small file
from GitHub and stays quiet on any failure, so being offline changes nothing.
Set TAKE_NOTES_NO_UPDATE_CHECK=1 to skip it entirely.
Issues and pull requests are welcome — CONTRIBUTING.md has the setup, the self-checks, and the four constraints that are easy to trip over. The most useful issue you can open is a source it handled badly, with the URL. Released changes are logged in CHANGELOG.md.
- bradautomates/claude-video by Bradley Bonanno (MIT).
If a note from this saved you rewatching an hour of video to find the one thing you actually needed, a star costs you nothing and is how the next person finds it. ⭐

