SkillsSkill for Claude

Stale guidance flag sheet

Give Claude what changed (an old approval limit, a retired system, a dropped step) and the recorded courses that may mention it, and it returns a review sheet with one row per moment where a trainer still says the old rule, a slide still shows it, or a demo still uses the old screen. Claude shortlists courses from their titles and outlines, prices the indexing against your Vivu plan, indexes the shortlist in a private Vivu project, searches speech and screen for each change, and checks every hit on frames and the transcript. Many LMS recordings have no transcript, and old limits often live only on a slide the trainer never reads aloud, so these moments are only in the picture. Whether each flag is outdated stays the content owner's call.

Maintained by Vivu. Updated 2026-09-28.

Download

stale-guidance-flag-sheet.zip

10 KB. Unzips to stale-guidance-flag-sheet/SKILL.md. Upload the zip as it is in the Claude app, or unzip it into your skills folder for Claude Code.

SHA-256 2ef3ac9aa0ca1a0077d2095f5661d1399169846a24b7680b713a70856b371d26

At a glance

What the Stale guidance flag sheet skill does, where it runs, what it needs, and when it asks
Looks forMoments where recorded training still carries old guidance: the old number on a slide, the old rule said aloud, or a demo of the retired system. Slide text and old screens are invisible to a transcript. Every hit is checked against the source video (contact sheet and full frame for slides and screens, transcript for speech) before it reaches the sheet, and slide text is read from the frame, not from Vivu's description.
Runs onClaude Code on your computer (terminal or the Code tab of Claude Desktop): it needs a shell with ffmpeg and the recordings as local files. No residential IP is needed because nothing is downloaded from YouTube, and nothing is scheduled.
Needs
  • The Vivu connector with write access, to create a private project, open its upload page and search
  • A shell with ffmpeg and ffprobe, to measure minutes and extract contact sheets and frames
  • The training recordings as local files, because frames come from them and Vivu has no export tool
  • The course list with titles and outlines, to index only the courses that can mention the change
  • A transcript per recording where one exists (LMS captions or local speech to text), because spoken rows quote it; without one, spoken hits stay marked uncertain
  • A browser that can open the Vivu upload page, since the connector has no direct upload tool
Your Vivu planIndexing uses Vivu index minutes for the shortlisted courses only, and each change item uses a spoken and an on screen precise search, with 5 credits per precise search. The skill measures the minutes with ffprobe, reads your allowance with vivu_get_usage and shows the cost before anything is uploaded. The Free plan has 20 index minutes a month, enough for a single short course; Premium is $30 a month.
Asks you firstIt asks before indexing the course shortlist and the change item queries, before uploading (with the minutes and credit estimate against your plan), and before writing the full sheet (with sample rows and the field mapping).

The skill does its video work through the Vivu connector. If the connector is not in your Claude yet, add it first; the skill checks that it is connected before it does anything else.

Before you run it

  • Index only recordings your organization owns or may upload to a third party service; vendor licensed courses may not allow it.
  • Ask whether any recording shows learners who did not agree to be recorded, and skip courses made for minors without guardian consent.
  • Vivu's screen text search can describe text that is not on screen, so slide hits are candidates until the number is read on the frame.
  • Recognizing an old system screen was only tested with its name visible in the title bar; unlabeled old screens are untested.
  • Spoken hits are confirmed from the transcript, because the reason text and summary segments paraphrase or skip the spoken rule.
  • Claude in Chrome uploads at most 10 MB per call; larger recordings are added in the Vivu web app, never split or recompressed.
  • Recordings stay in your Vivu project until you delete them, and the project is created private because the default is visible to the whole organization.
  • The skill flags where old guidance appears; whether it is outdated or non compliant is the content owner's decision, and it never grades trainers.
  • Nothing is sent on your behalf: the sheet stays in the working folder.

Start it

Once the skill is installed, ask for the task in your own words. Naming the skill is the most reliable way to have Claude use it. For example:

Our manager approval limit went from OLD_AMOUNT to NEW_AMOUNT and we retired OLD_SYSTEM. Here is the folder of recorded training and the course list: find where the videos still say, show or demo the old rules and give me a review sheet for the content owner.

In Claude Code you can also type /stale-guidance-flag-sheet. Claude asks for anything the request leaves out, most important first.

What is inside

  1. When to use
  2. Working principles
  3. What you need before starting
  4. Inputs to collect
  5. Files and state
  6. Step 1: Check the Vivu connector and the setup
  7. Step 2: Write the change items and shortlist the courses
  8. Step 3: Price the indexing and get approval
  9. Step 4: Upload and index
  10. Step 5: Run the searches and check every hit
  11. Step 6: Assemble staleflags.csv and confirm the sample
  12. Compliance
  13. Known failure modes

The full skill

This is stale-guidance-flag-sheet/SKILL.md from the download, as Claude reads it: the frontmatter first, then the instructions.

---
name: stale-guidance-flag-sheet
description: "After a policy or process change, find where recorded training still says, shows or demos the old rule with Vivu, and write a review sheet of timestamps for the content owner."
---

Stale guidance flag sheet for recorded training

This skill takes a list of what changed (an old approval limit, a retired form or system, a dropped process step) and the recorded courses that probably mention it, and returns stale_flags.csv: one row per moment where a trainer still says the old rule, a slide still shows it, or a screen demo still uses the old system. Claude shortlists the courses from their titles and outlines, prices the indexing against the user's Vivu plan, uploads the chosen recordings to a private Vivu project, runs two searches per change (one for speech, one for the screen), checks every hit on frames and the local transcript, and writes the sheet with video, change, start and end, where it appears, a frame, the words said, the slide text read from the frame, and an empty status column for the content owner.

The value is in what a transcript cannot hold. Many LMS recordings have no transcript at all, and when they do, it only has the words spoken. A trainer who says "take a moment to read this rule" while the slide shows the old limit leaves nothing in the transcript; a screen demo of the retired expense tool is narrated as "click here, enter the amount". Those moments only exist in the picture. Vivu's screen text search can confuse the old number with the new one or with a nearby number, so every slide hit is read from the frame before it reaches the sheet, and Claude only flags moments: whether each one is outdated is the content owner's call.

When to use

Use when someone in L&D, enablement or training ops says "the approval limit changed, which of our training videos still show the old one?", "find every course that demos the old expense tool", "audit our recorded onboarding for outdated policy", or "make a list of videos we need to re-record after the process change". For one question about one video ("does module 3 mention the old form?"), search Vivu directly. For turning a walkthrough recording into a written runbook, use a runbook skill instead; this one only flags moments for review. It does not rewrite or re-record anything.

Working principles

  1. Report measured numbers, not estimates. When a number is an estimate, say so.
  2. A moment goes on the sheet only after it has been checked against the frames or the local transcript. Vivu's results are candidates until then, and rejected candidates are counted and shown, not written as flags.
  3. Stop and tell the user when a required capability or file is missing (no transcript for a video, no ffmpeg, no write access in Vivu). Do not guess around it.
  4. Ask the user before anything that is expensive to redo or that acts on their behalf: the course shortlist before indexing, the indexing cost before upload, and the sample rows before the full sheet.
  5. Claude flags where the old guidance appears. Whether it is outdated, still acceptable in context, or a compliance problem is decided by the content owner, and the skill never grades the trainer.

What you need before starting

Check each item at the start of the run and tell the user plainly what is missing.

Requirement Why How to check
Vivu connector with write access create a private project, open its upload page, search vivu_get_account shows can_create_projects: true (tool names may carry a server prefix). A write call failing with "has not granted vivu.write" means the connection is read only; the user reconnects Vivu and allows write access
A shell with ffmpeg and ffprobe on the machine that holds the recordings measure minutes, extract frames and contact sheets ffmpeg -version and ffprobe -version
The recordings as local files (exported from the LMS, a shared drive or Zoom cloud recordings) frames come from the local files; Vivu has no export tool ls TRAINING_FOLDER
The course list with titles and outlines, or the LMS catalog export picks the courses to index without indexing the whole library the user pastes it or points to a CSV
A transcript per recording where one exists (the LMS caption file as SRT or VTT, or output of a local speech to text tool) spoken rows quote it, never Vivu's reason text; without it spoken hits stay marked UNCERTAIN, while slide and screen rows still work ls TRAINING_FOLDER for one .srt or .vtt per video; tell the user which videos have none
A browser that can open the Vivu upload page the connector has no direct upload tool the user opens the link, or Claude in Chrome is connected

The skill needs a shell and local files, so it runs in Claude Code on the user's computer. It downloads nothing from YouTube, so no residential IP is needed, and nothing is scheduled.

Inputs to collect

Ask for anything missing, most important first.

  1. The change items, two to four of them, each as old guidance and new guidance (for example: approval limit, old OLD_AMOUNT, new NEW_AMOUNT; expense tool, old OLD_SYSTEM, new NEW_SYSTEM). Required.
  2. The folder with the recordings (TRAINING_FOLDER) and the course list. Required.
  3. Which courses to index. Default: Claude proposes a shortlist from titles and outlines in Step 2.
  4. Where the old guidance could appear. Default: spoken and on screen for every change item; old system screens only for system changes.
  5. The Vivu project name. Default: "Training review CHANGE_NAME", private.

Files and state

Keep everything in one working folder next to the recordings:

stale-review/
  changes.json       change items: key, old guidance, new guidance, the spoken and on screen query for each
  courses.csv        shortlisted courses: file, title, why it was picked, minutes, transcript file
  results/           raw search results, one JSON file per query
  frames/            contact sheets and full frames used to check hits
  stale_flags.csv    the review sheet
  stale_flags_summary.txt  counts per change item, rejected candidates, courses with no flag
  state.json         uploaded files and video ids, queries run with job ids, every hit with its verdict, rows written

state.json is updated after every step. A rerun reads it first: files already uploaded are not uploaded again, queries already run are not rerun, and hits already checked keep their verdicts, so an interrupted run resumes where it stopped and no moment is written twice.

Step 1: Check the Vivu connector and the setup

Goal: every row of What you need is confirmed before anything is uploaded.

  1. Call vivu_get_account. If the tool is missing, tell the user to add the Vivu connector in Claude (https://mcp.vivu.ai/mcp) and stop. If can_create_projects is not true, or a write call later fails with "has not granted vivu.write", ask the user to reconnect Vivu with write access and stop until they have.
  2. Run ffmpeg -version and ffprobe -version. List the recordings folder and note which videos have a transcript file next to them.
  3. Create the working folders; ffmpeg does not create an output folder and stops with "Error opening output files: No such file or directory" if it is missing:
mkdir -p stale-review/results stale-review/frames

Run every later command from inside stale-review/ (cd stale-review), with VIDEO_FILE as the path to the recording from there, so frames/ and results/ resolve to the folders just created.

Done when vivu_get_account shows can_create_projects: true, ffmpeg and ffprobe print versions, and the working folders exist.

Step 2: Write the change items and shortlist the courses

Goal: changes.json with two to four change items and courses.csv with only the courses that can mention them.

  1. For each change item, write the old guidance the way a trainer would put it on a slide and the way they would say it. Numbers are the part that goes wrong, so write the old number exactly as the slides print it (OLD_AMOUNT such as "$500") and as it is spoken ("five hundred dollars"), and write down the new number and any other amounts in the same policy (a higher approval tier, a per diem) as look-alikes to watch for.
  2. Build two queries per change item, in plain words:
Field Query template Mode
CHANGE_slide a slide or on-screen text saying OLD_RULE_AS_WRITTEN precise
CHANGE_spoken the trainer mentions out loud OLD_RULE_AS_SPOKEN precise
CHANGE_ui (system changes only) a screen demo of the old OLD_SYSTEM TOOL_KIND precise

OLD_RULE_AS_WRITTEN is the old rule with the number in digits, OLD_RULE_AS_SPOKEN the same rule with the number in words and every noun a trainer might hang it on (for example "the five hundred dollar limit above which an expense or report needs a manager to approve it"), OLD_SYSTEM the retired system's name as it appears in its window title, TOOL_KIND what it is (expense tool, CRM, ticketing system). Why this chain: the spoken query finds where the trainer says the old rule, the slide query flips to where it is shown but maybe never said, and the UI query covers the old system that is only ever shown. All three are precise because the sheet needs time ranges; a fast search only returns whole files. 3. Read the course list (titles, outlines, module descriptions). Pick the courses whose outline touches a changed area: approvals, expenses, purchasing, the retired system. A library of several hundred hours cannot be indexed on any plan, and most of it never mentions the change. Write courses.csv with file, title, why picked, and transcript file. 4. Show the change items, the queries and the shortlist to the user and wait for a yes.

In our test run the courses were made for the test, so shortlisting from a real course catalog was not exercised in our test run; the change items and queries were written as above.

Done when the user has approved changes.json and courses.csv.

Step 3: Price the indexing and get approval

Goal: the user sees what the shortlist costs before anything is uploaded.

  1. Measure each file and sum the minutes:
ffprobe -v error -show_entries format=duration -of csv=p=0 VIDEO_FILE
  1. Call vivu_get_usage for the plan and what remains this month.
  2. Estimate search credits: two or three precise searches per change item. A precise search uses 5 credits in total; label the total as an estimate, since rewording a query and running it again adds to it.
  3. Show one table and wait for approval:
This review Remaining on the plan
Index minutes measured sum from vivu_get_usage
Search credits estimate from vivu_get_usage

For reference, the Free plan has 20 index minutes a month and 50 search credits a month, which covers one course of about 20 minutes; Premium is $30 a month with 180 index minutes and 500 search credits. If the shortlist does not fit, offer these levers in order: drop courses whose outline only touches the change in passing, split the review across months starting with the courses learners see most, and only then a larger plan. Never drop a course the user asked for without saying so.

In our test run the account was an admin account whose vivu_get_usage shows no remaining allowance, so the comparison against a real plan and the approval were not exercised in our test run.

Done when the user has approved the minutes and the credit estimate.

Step 4: Upload and index

Goal: every shortlisted recording is ready in a private Vivu project.

  1. Call vivu_list_projects and reuse the project named in the inputs if it exists. Otherwise call vivu_create_project with that name and visibility "private". Internal training often shows internal systems and people; the default visibility is the whole organization.
  2. Call vivu_open_upload_page with the project ID right before the upload. The link expires in 180 seconds and is a sign in link, so do not paste it into any message or file. Give it to the user to open in their own browser and choose the files from courses.csv, or attach the files with a browser tool that can upload local files. Claude in Chrome accepts at most 10 MB per upload call, and a 20 minute course is usually larger; the user adds those in the Vivu web app. Never split or recompress a recording to fit a tool limit.
  3. Poll vivu_list_videos about every 30 seconds until every file shows ready. Match each video back to courses.csv by file name; Vivu turns spaces and punctuation in names into the "_" character, so compare names with those characters replaced. Record the video IDs in state.json.

In our test run the files went up through a script, not through a user's browser or Claude in Chrome; that upload path was not exercised in our test run.

Done when vivu_list_videos shows every file in courses.csv as ready.

Step 5: Run the searches and check every hit

Goal: for each change item, a list of checked moments, with rejected candidates counted.

Run each query from changes.json with vivu_search_videos (project_id, query, mode "precise", maximum_results 20). It returns a job ID. Call vivu_get_search_results until complete is true; each status call can wait up to 45 seconds, so a pending search is not a stalled one. Save each completed result as results/FIELD.json, where FIELD is the query's field name from changes.json (for example approval_limit_slide) and VIDEO_FILE below is the local recording the hit points to. Show the result page link in the live reply only; it expires after four hours, so it never goes into stale_flags.csv or any file. maximum_results 20 is more than the times a shortlisted course normally mentions one rule, and it is also the ceiling on what comes back: a list that stops at exactly 20 means the cap was hit, so raise it and rerun that query.

Vivu returns a time range that contains the moment, not an exact frame, and the reason text is a paraphrase, not a transcript. Check every hit before it goes anywhere:

  1. For slide and UI hits, make a contact sheet of the whole window at two frames a second (START is start_ms / 1000, DURATION is (end_ms - start_ms) / 1000, N is the hit number, ROWS is DURATION x 2 / 6 rounded up):
ffmpeg -v error -ss START -t DURATION -i VIDEO_FILE -vf "fps=2,scale=320:-2,tile=6xROWS" -frames:v 1 frames/FIELD_hN_sheet.png

ROWS follows the window length (a 16 second window needs 6 rows, a 22 second window needs 8), so the last frames of the window, where the next slide can appear, are on the sheet. A fixed grid that is too small leaves the end of the window off the sheet.

Find the frames where the slide or the old screen is up, then extract one full size frame from that stretch (SECONDS is a time inside it) and read the text on it:

ffmpeg -v error -ss SECONDS -i VIDEO_FILE -frames:v 1 -q:v 3 frames/FIELD_hN_read.png

Keep the quotes around the filter; some shells treat the comma list as a pattern otherwise. 2. A slide hit is real only if the full frame shows the old guidance as written in changes.json, with the old number. Screen text reasons have described text that was not on screen in other Vivu tests (a price table on a page with no prices, a label that was not there), so the number is always read from the frame: a slide with the new number, a higher approval tier or another amount is rejected even if the reason names the old one. Look at the first and last frames of the window too, because a window can take in part of the next slide. Copy the slide text onto the sheet from the frame, never from the reason. 3. A UI hit is real only if the frame shows the old system's own window (its title bar, its menus), not the new system and not a slide about either. 4. For spoken hits, read the transcript lines inside the window. The hit is real only if the trainer states the old rule in words; the new rule, or the old rule shown on a slide while the trainer says "read this", does not count for the spoken field. Copy the words onto the sheet from the transcript. A video with no transcript keeps its spoken hits as candidates: write them with where set to "spoken, UNCERTAIN: no transcript" and said_local blank, so the content owner listens to that stretch before deciding; if the user can make a transcript with a local speech to text tool, check again after. As a second signal, vivu_get_video_summary with include_segments, start_ms and end_ms around the window shows what the section is about; its section boundaries are chapter level, so it never replaces the transcript. 5. Record every verdict in state.json with a short reason. Rejected hits stay in results/ and are counted, not written to the sheet. 6. An empty result does not prove a course never mentions the change. For courses on the shortlist with no checked hit, tell the user, and offer a contact sheet of the slides at one frame every two seconds for a quick look by eye. 7. If transcripts exist, also search them for the old rule with grep, with the number in digits and in words (for example grep -n -i "five hundred" TRANSCRIPT_FILE, where TRANSCRIPT_FILE is the video's .srt or .vtt). This is free and catches sentences the spoken search misses; the spoken search still matters for recordings without a transcript and for paraphrases the grep does not anticipate.

These are the wordings that ran in the test described below, for one limit change and one system change. Adapt the rule, the number and the system name to the user's change items and keep the shape:

Field Query Mode maximum_results
approval_limit_slide a slide or on-screen text saying manager approval is required for expenses over $500 precise 20
approval_limit_spoken the trainer mentions out loud the five hundred dollar limit above which an expense or report needs a manager to approve it precise 20
expense_tool_ui a screen demo of the old ClaimDesk Classic expense tool precise 20

The spoken wording names the number and both "expense" and "report", because the first, narrower wording ("expenses over five hundred dollars need a manager's approval") missed a trainer talking about approving a report above the limit.

Worked example from our test run

In our test run we used 4 synthetic training recordings, 3.2 minutes in total, made for the test with slides, a synthetic narrator and screen demos: an onboarding module, a manager course, a finance update that only shows the new rules, and a travel refresher where an old slide is followed by a look-alike slide with the new limit. The change items were a raised approval limit and a retired expense tool. We wrote down every place the old guidance appears before searching. The narration over the old slides never reads the number aloud, so the slide search could only succeed from the screen, and the slides shown while the old rule is spoken carry no number. From the upload to all 4 recordings ready took 3.3 minutes.

The slide query returned 3 moments: 3 real, 0 false and 0 missed. It returned none of the new limit slides, the higher approval tier slide or the per diem slide. The median window was 16 seconds, wider than the slides themselves; every window started on the course title card, and the travel refresher's window ran into the following slide with the new limit. That is why the sheet takes its times and text from the contact sheet and the full frame.

The spoken query first returned 1 moment, 1 real, 0 false and 1 missed. After 1 rewording on the same corpus it returned 2 moments: 2 real, 0 false and 0 missed, with a median window of 13.5 seconds. The new limit spoken aloud was never returned. The summary segments around both windows described the slide on screen and did not mention the spoken rule, so spoken hits are confirmed from the transcript, not from the summary.

The UI query returned 1 moment: 1 real, 0 false and 0 missed; the new tool's demo, with the same narration and the same clicks, was not returned. The old tool's name is printed in its title bar, so this did not test recognizing an old screen that carries no name.

The slides in the test are large, clean text on plain backgrounds. Busy slides, small print, screen recordings at low resolution and a real library of long courses were not part of the test, and the transcripts were the narrator's script rather than LMS captions or local speech to text output, so those cases were not exercised in our test run.

Done when every hit of every query has a verdict in state.json and the user has seen the true and false counts per query.

Step 6: Assemble stale_flags.csv and confirm the sample

Goal: the content owner gets one sheet, grouped by video and ordered by time.

  1. Build one row per checked moment. Narrow start and end to what the contact sheet and transcript show (the slide on screen, the sentence spoken), not the whole Vivu window:
video,change_item,start_mmss,end_mmss,where,frame,said_local,screen_text_from_frame,status
expenses_module3.mp4,approval_limit,00:05,00:17,slide,frames/approval_limit_slide_h1_read.png,,"Manager approval required for any expense over OLD_AMOUNT.",
  1. Field mapping:
Field Source If unavailable
video the original file name from courses.csv none
change_item the change key from changes.json none
start_mmss, end_mmss checked start and end inside the window, as MM:SS none
where spoken, slide or ui, from the query that found it and what the check confirmed none
frame path of the full frame read blank for spoken rows
said_local transcript lines inside the window blank for slide and ui rows
screen_text_from_frame read from the full frame blank for spoken rows
status left empty for the content owner: outdated, still OK, or needs discussion blank
  1. When one window holds both the old slide and the trainer saying the old rule, write two rows (slide and spoken), because the fixes differ: a slide can be patched, a spoken line needs a re-record or an edit.
  2. Show the user two or three sample rows and the mapping, and wait for a yes before writing the full sheet. Say which fields are inferred: where the slide ends is Claude's reading of the contact sheet, and if it is wrong the content owner jumps to a slightly wrong time.
  3. Write stale_flags.csv, and next to it stale_flags_summary.txt with the counts: checked flags per change item and per video, candidates rejected per query, and shortlisted courses with no flag. Hand the file to the user; the skill does not send it anywhere.

In our test run the sheet and the summary were built from the checked hits; the user's approval of the sample rows was not exercised in our test run.

Done when stale_flags.csv exists with one row per checked moment and the user has approved the sample rows.

Compliance

  1. Index only training recordings the organization owns or has the rights to upload to a third party service. Courses licensed from a vendor may not allow it; confirm before Step 4.
  2. People on camera: trainers and any learners visible in a live class recording were recorded for training. Ask before Step 4 whether any recording includes learners who did not agree to that, and leave it out if so. If a course was made for minors (a high school internship program, for example), do not index it without guardian consent.
  3. The skill flags where old guidance appears. It does not judge whether a moment is non compliant and does not evaluate the trainer; the content owner decides.
  4. The recordings stay in the user's Vivu project until the user deletes them. The skill never calls vivu_delete_video or vivu_delete_project unless the user asks, and confirms first. It does no face recognition and identifies no one.
  5. Nothing is posted or sent. stale_flags.csv stays in the working folder until the user shares it.

Known failure modes

Symptom Cause Fix
(observed) a slide window starts on the title card or runs into the next slide, which can show the new rule; in our test run the median slide window was 16 seconds Vivu returns a time range that contains the slide, not the slide's exact start and end take start, end and slide text from the contact sheet and the full frame, never from the window edges
(observed) the spoken search misses a sentence that states the old rule in another shape; the first wording in our test run returned 1 real and 1 missed the query described expenses needing approval, the trainer talked about approving a report above the limit name the number in the query, cover both nouns (expense or report), and grep the transcripts for the number in digits and words
(observed) the summary segments around a spoken hit describe the slide and say nothing about the spoken rule segment titles follow what is on screen, such as "Pre-submission checklist" confirm every spoken hit from the transcript lines inside the window
(observed) the reason text quotes a spoken rule with the number in digits, as if it were written the reason is a paraphrase, not a transcript copy said_local from the transcript, never from the reason
a slide hit's reason names the old number, but the frame shows the new number or a nearby amount screen text reasons can describe text that is not on screen read the number on the full frame and reject the hit if it is not the old one
an old system screen is not found when its name is not visible the UI search was only tested with the old tool's name in the title bar describe the old screen's layout in the query and look through contact sheets of the demo sections by eye
a list stops at exactly maximum_results the cap cut the list short raise maximum_results and rerun that query
a shortlisted course has no flag an empty result does not prove the course never mentions the change tell the user and offer a slide contact sheet of that course for a look by eye
"has not granted vivu.write" Vivu connected read only the user reconnects Vivu with write access
upload page asks to sign in or shows an error the one time upload link expires after 180 seconds request a new link right before opening it
a file is rejected by the browser upload tool Claude in Chrome takes at most 10 MB per upload call the user adds that file in the Vivu web app; never split or recompress it
a result's file name does not match courses.csv Vivu replaced spaces or punctuation in the name compare names with those characters replaced by "_"
ffmpeg stops with "Error opening output files: No such file or directory" the frames folder does not exist yet run the mkdir -p command from Step 1 and run later commands from inside stale-review/

Connect Vivu, then add the skill.

The skill runs through the Vivu connector. Add it to Claude from the connector directory, then install the skill.