refine
npx skills add https://github.com/olivoil/om-skills --skill refine
Agent 安装分布
Skill 文档
Refine Daily Notes
Improve an Obsidian daily note by polishing prose, adding missing wikilinks to maintain a rich knowledge graph, extracting long sections into dedicated notes, and suggesting new vault entities.
Workflow
Phase 0: Setup
- Run
echo $OBSIDIAN_VAULT_PATHto get the vault root. If empty, ask the user for the path. - Determine the target date: use the argument if provided (e.g.,
/refine 2026-02-14), otherwise use today. - Read the daily note at
$VAULT/ð Daily Notes/{date}.md. Error if missing.
Phase 1: Transcribe Meeting Recordings
Detect meeting recordings and transcribe them into meeting notes. Two sub-phases run in order: SD card auto-detect (primary), then Google Drive URL scan (fallback).
Phase 1a: Recording Detection & Matching (Primary)
-
Discover screen recordings:
bash skills/transcribe-meeting/scripts/find-screenrecordings.sh "{date}"Save JSON output to
/tmp/screenrecs-{date}.json. If no screen recordings found, use empty array[]. -
Discover Rodecaster recordings:
bash skills/transcribe-meeting/scripts/find-recordings.sh "{date}"Save JSON output to
/tmp/rodecaster-{date}.json. If SD card not mounted or no recordings found, use empty array[]. -
Match recordings by time overlap:
bash skills/transcribe-meeting/scripts/match-recordings.sh /tmp/screenrecs-{date}.json /tmp/rodecaster-{date}.jsonThis produces groups with
mode,video,audio, andtranscribe_fromfields.If both arrays are empty, skip to Phase 1b silently.
-
Check idempotency: For each group, search for existing meeting notes by both
recording:andvideo_file:fields:grep -rl 'recording: "{folder}"' "$VAULT/ðï¸ Meetings/" grep -rl 'video_file: "{filename}"' "$VAULT/ðï¸ Meetings/"Skip any group that already has a meeting note (matched by either field).
-
Match to time entries: For each new group, scan the daily note time entries for meeting-like entries. Use the recording start time and duration to correlate. Present to the user with mode info:
Found 2 recording groups:
- omarchy-only: screen recording from 09:36 (30 min) â no Rodecaster match. Match to
[[EWG]] - team standup - 0.5? - omarchy+rodecaster: screen recording from 11:02 + Rodecaster 10 (51 min). Match to
[[Khov]] - sync with Don - 1?
- omarchy-only: screen recording from 09:36 (30 min) â no Rodecaster match. Match to
-
Extract context from the matched time entry:
- Project: The wikilinked project name (e.g.,
[[Khov]]) - Description: The task/meeting description (e.g., “sync with Don”)
- Participants: Any names mentioned in the line or surrounding context
- Project: The wikilinked project name (e.g.,
-
Determine audio source for transcription:
omarchy+rodecasterâ audio = Rodecaster WAV (audio.path)omarchy-onlyâ extract audio from screen recording:bash skills/transcribe-meeting/scripts/extract-audio.sh "{video.path}"rodecaster-onlyâ audio = Rodecaster WAV (audio.path)
-
Transcribe inline (do NOT use Task/sub-agents â they lack bash permissions). For each new group:
a. Determine the engine:
echo $OBSIDIAN_WHISPER_ENGINE(defaults toopenaiif unset). b. Run transcription directly:bash skills/transcribe-meeting/scripts/transcribe.sh "{wav_path}" "{engine}"c. Capture the JSON output (array of
{start, end, text}segments). d. Generate a meeting note following the format inskills/transcribe-meeting/SKILL.mdPhase 3:- Title, Summary, Decisions, Action Items, Open Questions, Transcript
- Use context from the matched time entry (project, description, participants)
e. Present the summary to the user for approval before writing.
f. Create the meeting note at
$VAULT/ðï¸ Meetings/{date} {Title}.mdwith frontmatter: recording: "{folder}"(if Rodecaster audio exists)audio_url: "{wav_path}"video_file: "{video_filename}"(if screen recording exists)recording_mode: "{mode}"
Phase 3.5: Extract Key Screenshots (only when video recording exists):
Step 1 â Find user screenshots taken during the meeting:
bash skills/transcribe-meeting/scripts/find-screenshots.sh "{date}" "{start_time}" "{duration_secs}"This returns a JSON array of screenshots from
~/Pictures/(or$OMARCHY_SCREENSHOT_DIR/$XDG_PICTURES_DIR) taken during the meeting timeframe (±5 min buffer). Each entry haspath,timestamp, andoffset_secs.Step 2 â Copy and embed user screenshots: For each found screenshot:
- Copy to
$VAULT/ðï¸Attachments/{meeting-name}-user-{HH-MM-SS}.png - Place in the meeting note at the transcript position closest to its
offset_secs - Embed using
![[filename.png]]
Step 3 â Supplement with ffmpeg-extracted frames:
- If fewer than 3 user screenshots were found, scan the transcript for visual moments (screen sharing, demos, “as you can see”, “look at this”, code references, topic transitions) and extract additional frames to reach 3-8 total:
ffmpeg -ss {secs} -i "{video}" -frames:v 1 -q:v 2 -y "$VAULT/ðï¸Attachments/{name}-{MM-SS}.png" - If 3+ user screenshots were found, skip ffmpeg extraction entirely.
- If no user screenshots at all, fall back entirely to existing ffmpeg extraction behavior (select 3-8 key timestamps).
Embed all screenshots at corresponding transcript positions using
![[filename.png]]. -
Post-process & upload: After transcription completes for each group:
a. Compress WAV â MP3 and upload to Google Drive:
bash skills/transcribe-meeting/scripts/compress.sh "{wav_path}" bash skills/transcribe-meeting/scripts/upload-gdrive.sh "/tmp/meeting-archive/{filename}.mp3"Capture the Google Drive URL. Update
audio_urlin the meeting note.b. Merge video + audio (omarchy+rodecaster only):
bash skills/transcribe-meeting/scripts/merge-av.sh "{video.path}" "{audio.path}"c. Upload to YouTube (omarchy+rodecaster and omarchy-only):
bash skills/transcribe-meeting/scripts/upload-youtube.sh "{video_file}" "{meeting_title}" "{summary}" "{date}"- For
omarchy+rodecaster: upload the merged MP4 - For
omarchy-only: upload the original screen recording MP4 - Capture the YouTube URL. Update
video_urlin the meeting note.
- For
-
Update daily note: Append a wikilink to the matched time entry line:
- [[Khov]] - sync with Don - 1 - [[2026-02-18 Khov Sync with Don]] -
Update project note: If the project has a note in
$VAULT/ðï¸ Projects/, add a## Meetingssection (or append to existing) with a wikilink to the meeting note.
Present the transcription summary to the user for confirmation before writing the meeting note (consistent with refine’s preview-before-applying pattern).
Phase 1b: Google Drive URL Detection (Fallback)
Scan the daily note for Google Drive audio links and transcribe them into meeting notes.
-
Scan for audio URLs: Look for lines containing
drive.google.com/file/d/in the daily note text. -
Check for existing transcriptions: For each URL found, search
$VAULT/ðï¸ Meetings/for a note with matchingaudio_urlin frontmatter:grep -rl "audio_url:.*{file-id}" "$VAULT/ðï¸ Meetings/"If a meeting note already exists for this URL, skip it (idempotent).
-
Extract context: From the daily note line containing the URL, infer:
- Project: The wikilinked project name (e.g.,
[[Khov]]) - Description: The task/meeting description (e.g., “sync with Don”)
- Participants: Any names mentioned in the line or surrounding context
- Project: The wikilinked project name (e.g.,
-
Transcribe inline (do NOT use Task/sub-agents). For each new recording:
a. Download the audio:
bash skills/transcribe-meeting/scripts/download-gdrive.sh "{url}"b. Determine the engine:
echo $OBSIDIAN_WHISPER_ENGINE(defaults toopenaiif unset). c. Run transcription directly:bash skills/transcribe-meeting/scripts/transcribe.sh "{local_audio_path}" "{engine}"d. Capture the JSON output (array of
{start, end, text}segments). e. Generate a meeting note following the format inskills/transcribe-meeting/SKILL.mdPhase 3. f. Present the summary to the user for approval before writing. g. Create the meeting note at$VAULT/ðï¸ Meetings/{date} {Title}.md. -
Update daily note: Replace the Google Drive link in the daily note line:
- [[Project]] - description - hours - [recording](https://drive.google.com/...)To:
- [[Project]] - description - hours - [[{date} {Title}]] -
Update project note: If the project has a note in
$VAULT/ðï¸ Projects/, add a## Meetingssection (or append to existing) with a wikilink to the meeting note.
Present the transcription summary to the user for confirmation before writing the meeting note (consistent with refine’s preview-before-applying pattern).
If no recordings are found from either source, skip this phase silently.
Phase 1c: Meeting Action Items â Daily Todos
After all meeting notes are created (from Phase 1a and 1b), extract action items and propose them as daily todos.
- Collect action items: For each newly created meeting note, read its
## Action Itemssection. - Filter for Olivier’s items: Extract items assigned to Olivier (look for
@Olivier,Olivier:, or unattributed items from 1:1 meetings where Olivier is a participant). - Map to projects: Use the meeting frontmatter
project:field to determine which project section each item belongs to. - Check for duplicates: Fuzzy-match each proposed todo against existing todos in the daily note. Skip items that are already present (even if worded slightly differently).
- Present proposed insertions grouped by project:
From [[2026-02-20 EXSQ Sol 1-1 Sync]]:
- [[EXSQ]] – Set up Claude Code access for Sol
- [[EXSQ]] – Explore Figma + GitHub integration feasibility
- If approved, insert under the matching project heading in the daily note’s todos section. If no matching heading exists, create one using
### [[Project]]format. - Format:
- [ ] [[Project]] - task description (from [[Meeting Note]])with nested sub-items if the action item has sub-tasks.
If no new meeting notes were created or no action items found, skip this phase silently.
Phase 2: Discover Vault Entities
Build a catalog of all known entities so you can match them against the daily note text.
- Projects: List files recursively in
$VAULT/ðï¸ Projects/â extract project names from filenames - People: List files in
$VAULT/ð¤ Persons/â read each file to extractaliasesfrom frontmatter - Topics: List files in
$VAULT/ð Topics/â extract topic names from filenames - Coding sessions: List files in
$VAULT/ð» Coding/â for cross-reference awareness - Meetings: List files in
$VAULT/ðï¸ Meetings/â for cross-reference awareness and to avoid duplicate transcription
This gives you the full entity catalog to match against the daily note.
Phase 2b: Slack Activity Scan
Always run this phase. If Slack MCP tools are unavailable, skip gracefully with no error.
- Load Slack tools: Use
ToolSearchto search forslacktools. If no Slack MCP tools are available, skip this phase with no error â but always attempt it first. - Search for user’s messages on the target date using
slack_search_public_and_private:- Query:
from:<@U07J89FDWPJ> on:{date}
- Query:
- Group messages by channel and 30-minute time windows.
- Build a time coverage map from existing daily note time entries (start times, durations, projects).
- Identify gaps: time windows with 3+ Slack messages but no matching time entry.
- Detect huddles: For each DM or group DM channel found in step 2, read messages around the activity window using
slack_read_channelwitholdest/latesttimestamps. Look for messages from Slackbot containing"A huddle started".- Slack’s search API does not index huddle system messages â they can only be found by reading the channel directly.
- When a huddle is found, record:
- Start time: the Slackbot message timestamp
- Participants: inferred from the DM/group DM members (the channel context)
- Estimated duration: gap between the huddle start and the next human message in the channel (rough estimate â Slack does not expose huddle duration via API)
- Huddles should always have a corresponding time entry. Flag any huddle that doesn’t match an existing entry.
- Infer channelâproject mapping from channel names and existing time entries:
- Check cached mappings in
$VAULT/.claude/intervals-cache/slack-mappings.md - If a new channelâproject mapping is discovered, append it to the cache file
- Check cached mappings in
- Present findings:
Slack activity not covered by time entries:
- #technomic-dev (2:30-3:15pm, 8 messages): discussed vector search PR issues â [[Technomic]]?
- #exsq-general (4:00-4:20pm, 4 messages): coordinated with team on AI Upskill â [[EXSQ]]? Add time entries for these?
Huddles detected:
- DM with [[Sol Parrot|Sol]] (12:16pm, ~1h54m): matches
[[EXSQ]] - 1:1 sync with Sol - 2â - DM with [[Adam Herrneckar|Adam]] (3:05pm, ~25m): no matching time entry â add one?
- If approved, suggest time entry lines but do NOT auto-insert into time entries â present them for the user to manually add (time entries are sacred structured data).
Phase 3: Analyze & Improve Writing
Review each section of the daily note:
- Skip time entries â the bullet list at the top (lines like
- [[Project]] - task - duration) is structured data for the intervals skill. Never modify these. - Improve prose â fix grammar, improve clarity, tighten wording. Keep it concise.
- Fix formatting â consistent heading levels, list styles, spacing.
- Preserve todos â don’t reorder, rewrite, or change checkbox state. Only improve prose around them.
- Author’s voice â improve clarity without rewriting the user’s natural style. Don’t make it sound like AI wrote it.
Phase 4: Add Missing Wikilinks
Scan all text (outside time entries) for mentions of known entities:
- Projects: Add
[[Project Name]]links where project names appear unlinked - People: Add
[[Full Name]]or[[Full Name|Alias]]when a short name or alias is used - Topics: Add
[[Topic]]links where topic names appear unlinked - Heading style: Use
### [[Project]]for project section headings consistently
Rules:
- Don’t double-link â skip text already inside
[[...]] - Don’t link inside time entry lines
- Link known entities freely without asking the user
Phase 5: Extract Long Sections
Identify sections that are >~20 lines or contain substantial standalone content worth its own note.
For each extractable section:
- Determine destination:
ðï¸ Projects/subtree orð Topics/based on content - Create the new note with proper format:
# {Title} {Extracted content} ## Related - [[ð Daily Notes/{date}]] - Replace the section in the daily note with a brief summary +
[[wikilink]]to the new note
Present all proposed extractions to the user for approval before executing. Show what would be extracted, where it would go, and what the replacement summary would look like.
Phase 5b: Suggest New Entities
Identify mentions of people, projects, or topics that don’t match any existing vault note.
Present these as candidates:
It looks like **Jane Smith** and **ProjectX** are mentioned but don't have vault pages yet.
Want me to create them?
For each confirmed new entity, create the note following vault conventions:
-
Person:
$VAULT/ð¤ Persons/{Name}.md--- aliases: - {short name} --- # {Full Name} **Role**: {if known} **Projects**: {if known} ## Notes -
Project:
$VAULT/ðï¸ Projects/{Name}.md(or appropriate subdirectory)# {Project Name} {Brief description if known} ## Related -
Topic:
$VAULT/ð Topics/{Name}.md# {Topic Name} {Brief definition if known} ## Related ## Notes
After creating new entities:
- Add them to the respective MOC file (e.g., Persons MOC, Topics MOC) if one exists
- Link them in the daily note (they now exist as vault pages)
Phase 5c: Suggest Todo Completions
Scan unchecked todos against today’s content to suggest completions with high confidence.
- Collect unchecked todos from the daily note (lines matching
- [ ]). - Build an evidence corpus from:
- Meeting note
## Decisionsand## Action Itemssections (items marked complete) - Coding session summaries and files changed (from
ð» Coding/notes for this date) - PR review verdicts (merged PRs mentioned in notes)
- Daily note prose sections
- Meeting note
- Match todos to evidence â for each unchecked todo, check for HIGH confidence matches only:
- Strong keyword overlap between todo text and evidence
- Explicit completion signals (“merged PR #X”, “completed”, “done”, “shipped”, “deployed”)
- Present suggestions with evidence:
These todos appear done based on today’s work:
review PRsâ Evidence: wrote detailed reviews for PRs #650, #636, #571, #469fix vector searchâ Evidence: coding session [[2026-02-20–TechnomicIgnite–fix-vector-search]] shows fixes deployed Mark as complete? (â 2026-02-20)
- If approved, check off the todos: change
- [ ]to- [x]and append completion date(â {date}).
Rules:
- Never suggest more than 5 completions at once
- Skip anything below ~80% confidence â better to miss one than suggest a false positive
- Never auto-complete without user approval
- If no high-confidence matches found, skip this phase silently
Phase 6: Apply & Confirm
- Show a summary of all proposed changes before writing:
- Prose improvements (brief description)
- Wikilinks added (list them)
- Sections extracted (destination paths)
- New entities created (paths)
- Get user approval before applying
- Apply changes: edit the daily note, create any extracted/new entity notes
- Report: what was changed, what was linked, what was extracted, what was created
Phase 7: Update Project Recent Activity
After all daily note changes are applied, update each referenced project’s note with a summary of today’s activity.
- Identify projects from today’s time entries in the daily note.
- For each project with a note in
$VAULT/ðï¸ Projects/:- Read the existing
## Recent Activitysection (or prepare to create it) - Build today’s entry:
- **{date}**: {hours}h â {brief summary} (meetings: [[links]], coding: [[links]]) - Prune entries older than 7 days from the section
- Insert the
## Recent Activitysection before## Key Featuresor at the end of the note if no logical insertion point
- Read the existing
- Check idempotency: If an entry for today’s date already exists, update it rather than duplicating.
- Present all proposed project note updates for approval before applying.
- Apply changes if approved.
Phase 7b: Update Person Interaction History
Update person notes for anyone who appeared in today’s meetings.
- Collect participants from all newly created meeting notes (from frontmatter
participants:field). - For each person with a note in
$VAULT/ð¤ Persons/:- Read the existing
## Recent Interactionssection (or prepare to create it) - Build entry:
- **{date}**: [[Meeting Note]] â {topics discussed, action items for/from them} - Prune entries older than 30 days from the section
- Insert the
## Recent Interactionssection before## Notesor at the end of the note
- Read the existing
- Check idempotency: If an entry for today’s date + same meeting already exists, skip it.
- Present all proposed person note updates for approval before applying.
- Apply changes if approved.
If no new meeting notes were created or no participants have vault pages, skip this phase silently.
Key Rules
- Never modify time entries â the bullet list at the top is structured data
- Preserve todos â only improve prose around them
- Link known entities freely â no need to ask for entities that already exist
- Offer to create unknown entities â ask before creating new vault pages
- Author’s voice â improve clarity without rewriting style
- Idempotent â running twice shouldn’t cause issues (don’t re-extract already-extracted sections, don’t double-link)
- Show before applying â always preview changes for user approval