CommunityProductivity & Collaborationgithub.com

recording-to-obsidian

Turn a meeting recording or a lecture's materials (audio/video, transcripts or subtitles, slides pdf/pptx, notebooks, code, handouts, whiteboard photos) into linked Obsidian notes. Transcribes recordings locally with Whisper (bundled script). Meeting mode writes a meeting hub (TL;DR, decisions, action items in Obsidian Tasks format with owners, due dates and transcript timestamps), ADR-style decision records, durable topic notes and a series MOC. Lecture mode writes a lecture MOC, dense anchor notes and fine-grained atomic notes with PDF++ slide links and Mermaid diagrams. Use whenever the user wants meeting minutes, a recap, action items, study notes, a MOC or a knowledge base from a meeting, a call, a class or a talk — even if they only say 'make notes from this recording'.

What is recording-to-obsidian?

recording-to-obsidian is a Claude Code agent skill that turn a meeting recording or a lecture's materials (audio/video, transcripts or subtitles, slides pdf/pptx, notebooks, code, handouts, whiteboard photos) into linked Obsidian notes. Transcribes recordings locally with Whisper (bundled script). Meeting mode writes a meeting hub (TL;DR, decisions, action items in Obsidian Tasks format with owners, due dates and transcript timestamps), ADR-style decision records, durable topic notes and a series MOC. Lecture mode writes a lecture MOC, dense anchor notes and fine-grained atomic notes with PDF++ slide links and Mermaid diagrams. Use whenever the user wants meeting minutes, a recap, action items, study notes, a MOC or a knowledge base from a meeting, a call, a class or a talk — even if they only say 'make notes from this recording'.

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/T0MYYY/recording-to-obsidian/tree/HEAD/skill/recording-to-obsidian

Installed? Explore more Productivity & Collaboration skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

What does recording-to-obsidian do?

Turn one meeting or one lecture into a self-contained, fully linked part of an Obsidian vault. Both modes share the pipeline, the conventions and the verification step; they differ in what they extract and how the notes are shaped.

Meeting modeLecture mode
Purposeremember what was decided and who does what by whenre-learn the ideas quickly at any time
Hubone meeting hub per session + a series MOC with one entry per meetingone MOC per lecture
Body notesADR-style decision records; topic notes for durable knowledgeanchor notes (dense) + atomic notes (one idea each)
Traceabilitytranscript timestamps [00:12:34] on decisions and action itemsPDF++ slide links [[deck.pdf#page=5]]; timestamps for spoken-only content
Referencereferences/meeting-mode.mdreferences/lecture-mode.md

<skill> below means the folder this file is in.

1. Pipeline

materials ──► 1 setup ──► 2 transcribe ──► 3 pick mode ──► 4 note-writer ──► 5 verify ──► 6 report
             config,      scripts/          meeting or      writes notes     check_vault
             python       transcribe.py     lecture          (one subagent)   scan_secrets

1.1 Setup

Note the start time first: run date +%s and keep the number; verification checks only notes written after it.

Read <skill>/config.toml. It sets the transcription backend/model/language, diarization, notes.output_language, notes.default_mode and the vault folder names (notes_dir, moc_dir, meetings_dir, sources_dir; defaults used below). The interpreter for the scripts is runtime.python; if that is empty use ~/.local/share/recording-to-obsidian/venv/bin/python. Call it $PY — that is notation: in commands write the interpreter's and the scripts' full literal paths, one command per call, without shell variables or cd … && chains (agent permission rules match the literal command, and variables make it uncheckable). If it does not exist, tell the user to run install.sh (README) — do not pip-install into the user's own Python environments.

Establish the facts before anything else (ask only for what you cannot infer):

  • vault — the user's path, else the current working directory if it contains .obsidian/ or the user said "this vault"; write only inside it;
  • materials — absolute paths of every file; classify each by extension: audio/video, subtitles (.srt/.vtt), slides (.pdf/.pptx), notebooks/code, images/photos, documents;
  • title, series/course, date — from the user, file names, or the materials; never invent a date or attendee list (write TBD and say so);
  • output language — notes.output_language unless the user asked for one.

1.2 Transcribe

For every recording without a matching subtitle file (same stem), run:

$PY <skill>/scripts/transcribe.py <recording> -o <scratch>/transcripts
  • <scratch> is a temporary folder outside the vault (e.g. $TMPDIR/recording-to-obsidian-<date>-<slug>), used for all intermediate files.
  • Options when needed: --model small (faster, rougher), --language en (skip detection), --diarize (speaker labels; needs install.sh --diarize and a Hugging Face token in the env var named by diarize.hf_token_env). A first run downloads the model, which can take minutes; it prints progress on stderr — let it finish.
  • It writes <stem>.srt and <stem>.txt (one [HH:MM:SS] Speaker N: text line per segment) and prints a JSON summary line (language, model, duration, speakers, cleaning stats, file paths). Keep that summary: language, model and diarization go into the notes' Source section.
  • Existing subtitles from any tool can be normalised the same way: $PY <skill>/scripts/transcribe.py talk.vtt -o <scratch>/transcripts (no model involved; repetition loops are folded and a .txt with timestamps is written).
  • Long recordings are fine: the script handles hours of audio; do not split the file.

If transcription fails, report the error line; $PY <skill>/scripts/transcribe.py --check shows what is missing.

1.3 Pick the mode

An explicit mode from the user (or notes.default_mode other than auto) wins. Otherwise:

  1. Slides, notebooks, lab code or handouts among the materials → lecture.
  2. Else read the first ~5 minutes of the transcript and skim the rest:
Meeting signalsLecture signals
several speakers with comparable airtimeone dominant speaker explaining
agenda, status updates, "where are we on…""today we'll cover…", "last week we saw…"
proposals, trade-offs argued, "let's go with…", "agreed"definitions, derivations, worked examples, exercises
owners and dates: "can you take that by Friday?"audience questions asked to understand, not to decide
projects, customers, deadlines, riskscourse / lecture numbering, readings, homework
  1. Mixed cases go by purpose: design reviews, planning, retros, debriefs and 1:1s are meetings; recorded tech talks, trainings, seminars and tutorials are lectures, even with some discussion.

Record the choice and the two or three signals that drove it (they go in the report). If it is a genuine toss-up and you can ask, ask; otherwise pick and say why.

1.4 Execution model: orchestrator + one note-writer

Reading a whole transcript, a deck page by page and notebooks, then writing tens of files fills a context window fast, so split the roles:

  • Orchestrator — the session that received the request. It does 1.1–1.3 (transcription output stays on disk; it reads only enough of the transcript to pick the mode), hands the writing to one note-writer subagent, then runs the verification in 1.5 and reports.
  • Note-writer — one subagent that does the whole writing job for the chosen mode in its own context: read every material, plan, write, self-check. One meeting or one lecture fits comfortably in one context; do not split pages or transcript chunks across agents (that loses cross-references and duplicates notes).

Do the work yourself instead of delegating when no subagent tool is available, when a subagent could not do what the job needs (see images, run scripts, write files). In meeting mode you may also write directly when the meeting is short enough that the brief would be as long as the work (a recording under ~15 minutes with no slides or documents). Lecture mode always uses the note-writer unless a subagent is unavailable or cannot do the job: a deck has to be read page by page, and that belongs in the writer's context, not yours. Say which you chose in the report. Verification (1.5) is never skipped. For several sessions, use one note-writer per session, sequentially when they append to the same MOC.

Brief for the note-writer — it starts with no context, so give it everything:

  • this skill's absolute path; the mode; the files to follow: references/meeting-mode.md or references/lecture-mode.md, plus references/note-templates.md, references/transcript-processing.md, references/mermaid-style.md;
  • vault path, scratch folder, $PY, output language, title/series/date (or "derive"), folder names from config;
  • absolute paths of every material and of the transcript files, with the transcription summary (language, model, speakers);
  • the existing series/course MOC and the previous session's hub/MOC if any; anything the user asked for specifically;
  • rules: write only inside the vault; never modify pre-existing notes except the documented appends; no secrets;
  • what to return: the report block from Section 3 plus anything it could not resolve.

1.5 Verify (orchestrator)

When the note-writer returns, check its work independently rather than trusting its summary:

$PY <skill>/scripts/check_vault.py <vault> --since <epoch seconds when the job started>
$PY <skill>/scripts/scan_secrets.py <vault>/sources

check_vault.py must end with issues: 0; fix warnings too unless there is a reason not to (say which). It resolves links the way Obsidian does (file name or partial path, case-insensitive, ignoring #heading/|alias, skipping code blocks), so a broken link it reports is broken in Obsidian. It checks: broken [[links]]/embeds/markdown links, PDF++ links without .pdf, frontmatter (title, type, date_created), hub coverage (every new note is linked from a MOC or meeting hub; every meeting hub from a MOC), secrets; warnings for notes without connections, unstyled Mermaid and ambiguous links.

Then check what the scripts cannot:

  • no pre-existing note changed except the documented appends (series MOC entry, superseded decision status, previous lecture MOC's "next" link);
  • meeting mode: every decision has a record or is explicitly minor; every action item has an owner (or TBD), a due date (or TBD) and a timestamp;
  • lecture mode: the MOC lists every new note exactly once; the granularity and anchor targets of the lecture self-check are met.

Fix small problems directly; send larger ones back to the note-writer with the exact list. Re-run check_vault.py until it reports 0 issues. Delete the scratch folder (it contains the wav and page images) unless the user wants it.

2. Shared conventions

Vault layout — notes are flat; navigation comes from MOCs and hubs, not folders.

vault/
├── notes/                         # atomic, anchor, decision and topic notes (flat)
├── meetings/<series>/             # meeting hubs: "YYYY-MM-DD <title>.md"
├── moc/<series or course>/        # series MOC (meetings) / one MOC per lecture
└── sources/<series or course>/<YYYY-MM-DD or Lecture_NN>/
    ├── <prefix>_transcript.srt / .txt
    ├── <prefix>.pdf               # slides, for PDF++ links
    ├── slide_images/  whiteboard_photos/  notebooks/
    └── structured_slides.json     # optional per-page reading record

Give every file copied into sources/ a series/course + session prefix (Atlas_2026-11-12_transcript.srt, Optics101_L03.pdf, Optics101_L03_p08.jpg): Obsidian resolves links by file name, so two sessions that both contain transcript.srt or page-08.jpg would cross-link. Folder names use the series/course name with spaces replaced by -.

File names — the human-readable title, no IDs (meeting hubs are the exception: they start with the date so they sort). Avoid / \ : * ? " < > | # ^ [ ]; write — instead of :. Titles are specific enough to stand alone: Rate limits use a token bucket per API key.md, not Rate limiting.md.

Frontmatter — every note starts with YAML frontmatter with at least title, type and date_created. type is moc, meeting, decision or topic (meeting mode) and moc, anchor or atomic (lecture mode). Mode-specific fields are in references/note-templates.md. Tags are lowercase English kebab-case: one series/course tag, 2–4 topic tags, one type tag; reuse tags already in the vault before inventing new ones.

Language — output_language = "auto" means: write in the language of the materials (the transcript's detected language, or the slides'). When the output language differs from the materials' language, keep technical terms in the original language and gloss each on first occurrence — Chinese notes from an English meeting: 功能开关 (feature flag); English notes from a German lecture: error propagation (Fehlerfortpflanzung) — then use whichever form reads naturally. Code, commands, paths, product and tool names are never translated. Headings follow the output language.

Links — every [[wikilink]] must resolve to a note or file in the vault. Link to an existing note instead of writing a duplicate. Use a path ([[sources/Atlas/2026-11-12/Atlas_2026-11-12_transcript.srt|transcript]]) when a bare name could be ambiguous. PDF++ page links always keep .pdf: [[Optics101_L03.pdf#page=5|Slide p.5 "Snell's law"]].

Timestamps — cite the transcript's [HH:MM:SS] for every decision, action item and claim that comes only from speech. They are the audit trail back to the recording.

Secrets — never write credentials into the vault. Before copying notebooks or code into sources/, run $PY <skill>/scripts/scan_secrets.py --redact <copy> on the copy (values become <REDACTED>, variable names stay). Spoken passwords, card numbers or sensitive personal data in a meeting are not minuted either — write "credentials were shared verbally (not recorded here)".

Visuals — read references/mermaid-style.md before writing any Mermaid diagram: it has the palette and the rules that keep diagrams rendering. Invalid syntax is worse than no diagram.

Mode outputs

  • Meeting → references/meeting-mode.md: 1 hub, 1 decision record per significant decision, 0–N topic notes for knowledge worth keeping, one entry appended to the series MOC (created on first use), transcript copied to sources/.
  • Lecture → references/lecture-mode.md: 1 MOC, 8–15 anchor notes for a normal 30+ page deck, on average at least one atomic note per content slide, slides/notebooks/transcript copied to sources/.

3. Report

Meeting mode:

Meeting 2026-11-12 — <title>  (series: <series>)   mode: meeting (signals: …)
  Transcript: 00:41:07, mlx:whisper-large-v3-turbo, 3 speakers, en → notes en
  Hub: meetings/<series>/2026-11-12 <title>.md
  Decisions: 3 (records: 3)   Action items: 7 (owner TBD: 1, due TBD: 2)
  Topic notes: 2   Open questions: 2   Risks: 1
  Series MOC: moc/<series>/MOC — <series>.md (entry appended)
  check_vault: issues 0, warnings 0
  Unresolved: <speakers not matched to names, unclear passages, …>

Lecture mode:

Lecture NN — <topic>   mode: lecture (signals: …)
  Slides: 45 pages (content 37)    Knowledge points: 68
  Notes: 56 atomic + 12 anchor     archetypes: concept=34, practice-demo=6, …
  Notes per content slide: 1.5     Anchors with ≥2 rich elements: 12/12
  Mermaid: 14 (types: sequence, mindmap, flowchart, …)   Slide images: 11
  check_vault: issues 0   MOC coverage: 68/68
  MOC: moc/<course>/MOC — … .md      Sources: sources/<course>/Lecture_NN/
  Unresolved: …

Related Skills