SkillsSkill for Claude

Usability test recordings to issue tickets

Hand Claude a folder of usability session recordings (UserTesting, Maze or Lookback exports, Zoom or Loom recordings) and get back a list of issues for the design team, each with a short clip, ready to file in Linear with one summary in Slack. Error dialogs often go unmentioned, especially by silent testers in unmoderated tests, so a transcript misses them, and even a confused remark needs the screen behind it before a designer can act. Claude indexes the round in Vivu, searches for confused remarks and error dialogs, checks every moment against the recording and the transcript, looks at the pointer around each one for hesitation, groups the moments by screen and cuts the clips.

Maintained by Vivu. Updated 2026-09-25.

Download

usability-test-issue-tickets.zip

10 KB. Unzips to usability-test-issue-tickets/SKILL.md. Upload the zip as it is in the Claude app, or unzip it into your skills folder for Claude Code.

SHA-256 0f33f18027aec8d84f3ee5808211b2f018dac74a9b8524f75d946d8f888ad549

At a glance

What the Usability test recordings to issue tickets skill does, where it runs, what it needs, and when it asks
Looks forMoments where a tester says out loud that they are confused or cannot find something, and moments where an error dialog appears on screen, often without a word from the tester. Each one is checked against the recording (frames for dialogs, the transcript for remarks) before it goes into an issue; pointer hesitation near those moments is added only as a candidate note.
Runs onClaude Code on your computer (terminal or the Code tab of Claude Desktop), because clips and frames are cut from your local recordings with ffmpeg. It downloads nothing from public sites, so no residential IP is needed, and it runs once per test round with no scheduler.
Needs
  • The Vivu connector with write access, to create a project, upload, search and read section summaries.
  • The session recordings as local video files, because clips and frames are cut from the originals.
  • A transcript for each session with speech, because quotes come from the transcript and not from Vivu's paraphrase.
  • ffmpeg and ffprobe on your computer, for durations, frames, contact sheets and clips.
  • A browser to open the one time upload link, or a browser tool that can attach local files.
  • The Linear connector, only if issues should be filed in Linear.
  • The Slack connector, only if a summary should be posted to Slack.
Your Vivu planIndexing uses as many index minutes as the sessions are long, and each round runs two precise searches (about 10 search credits, estimate). The skill shows these against your plan and waits for approval before uploading. In our test run two new short sessions used 2.47 index minutes.
Asks you firstBefore uploading, that the testers' consent covers analysis in a third party tool; before indexing, with minutes and credits shown against your plan; before writing every issue row, with one sample row and the field mapping; and before creating Linear issues or posting to Slack, with one complete issue and the complete message shown first.

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

  • Pointer hesitation is not searched for: in our test run Vivu's hesitation search returned too many false ranges and read narration as pointer movement. Hesitation is only noted as a candidate near confirmed moments.
  • A tester who is stuck but says nothing and sees no error is not covered by this skill.
  • Session recordings show testers and what they type. Confirm their consent covers a third party tool, check clips for personal data before they go into Linear, and stop for any tester under 18 without guardian consent.
  • Recordings stay in your Vivu project until you delete them; the skill creates the project as private.
  • Creating Linear issues and posting to Slack act as you and need your approval of a complete sample first; this step was not exercised in our test run.
  • Claude in Chrome accepts at most 10 MB per upload call; larger recordings go in through your browser or the Vivu web app.

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:

Go through the usability sessions in ~/Research/round-7/ and draft Linear issues for where testers got stuck, with a clip for each.
Team is DESIGN. Post a summary to #ux-research when I approve.

In Claude Code you can also type /usability-test-issue-tickets. 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: Measure the sessions and price the round
  8. Step 3: Create the project and upload
  9. Step 4: Run the two searches
  10. Step 5: Check every moment
  11. Step 6: Look for hesitation around each moment
  12. Step 7: Group into issues and cut clips
  13. Step 8: File the issues in Linear and notify Slack
  14. Compliance
  15. Known failure modes

The full skill

This is usability-test-issue-tickets/SKILL.md from the download, as Claude reads it: the frontmatter first, then the instructions.

---
name: usability-test-issue-tickets
description: "Turn a folder of usability test recordings into draft Linear issues with a short clip each; Vivu finds where testers said they were confused or hit an error. Use after a test round."
---

Usability test recordings to issue tickets with Vivu

This skill turns a round of recorded usability sessions into issues the design team can act on. The user hands over a folder of session recordings (exports from UserTesting, Maze or Lookback, or Zoom and Loom recordings). Claude indexes them in Vivu, searches for the moments where a tester says out loud that they are confused and the moments where an error dialog appears on screen, checks each moment against the recording, looks at the pointer around each one for signs of hesitation, groups the moments into issues by screen, cuts a short clip for each, and, with the user's approval, files the issues in Linear and posts one summary to Slack.

The value is in what happens on screen while the tester talks, or while they say nothing. An error dialog like "Payment method declined" often goes unmentioned, especially in unmoderated tests where many testers stay silent, so a transcript never shows it. A remark like "where do I put the promo code?" is in the transcript, but the designer needs to see which page the tester was on and what they were looking at, and the clip is what goes into the ticket. Vivu finds both kinds of moment; Claude checks every one in the recording before it becomes part of an issue.

When to use

Use when someone asks to "go through these usability test recordings and file the problems", "turn our user testing videos into Linear tickets", "find where testers got stuck", or wants a summary of a test round for designers without watching every session. For a single question about one session ("what did tester 3 say about pricing?"), search Vivu directly instead. For a pile of dozens of hours of old sessions, pick one round or one task first (Step 2 explains why). If the goal is to find testers who hesitated silently without speaking or hitting an error, this skill cannot do that reliably; Step 6 explains the limit.

Working principles

  1. Report measured numbers, not estimates. When a number is an estimate, say so.
  2. Nothing is "verified" until it has been checked against the source video. A search result is a candidate until Claude has looked at frames or read the transcript for that moment.
  3. Stop and tell the user when a required capability or tool is missing. Do not guess around it.
  4. Ask the user before anything that is expensive to redo or that acts on their behalf: indexing (it uses plan minutes), creating Linear issues, and posting to Slack.
  5. Hesitation seen on the pointer is a note on an issue, never an issue on its own. Vivu's search for pointer movement was not reliable enough in our test run to report from (Step 6).
  6. Testers are people who agreed to be recorded for research. Their names stay out of issues and messages; sessions are referred to by file name.

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 project, open its upload page, search, read section summaries 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; ask the user to reconnect Vivu and allow write access
The session recordings as local video files clips and frames are cut from the originals; the Vivu connector has no export tool the user gives the folder; ffprobe reads each file in Step 2
A transcript for each session with speech quotes in issues come from a transcript, because Vivu's reason text paraphrases the testing platform's transcript export, or a local speech to text tool; open one file
A shell with ffmpeg and ffprobe on the user's computer (Claude Code in the terminal or the Code tab of Claude Desktop) durations, frames, contact sheets, clips ffmpeg -version and ffprobe -version
An upload path moving the recordings into Vivu vivu_open_upload_page plus the user's own browser, or a browser tool that can attach local files
Linear connector, only if issues go to Linear Step 8 creates the issues list the teams once and confirm the target team is there
Slack connector, only if a summary goes to Slack Step 8 posts one message read the target channel once

This skill runs once per test round. It needs no scheduler and no residential IP, because it downloads nothing from public sites. Without Linear or Slack it still produces the issue list, the clips and a draft message in the working folder.

Inputs to collect

Ask for anything missing, most important first.

  1. The folder of session recordings. Required. Unmoderated platforms let the study owner download each session as an MP4; if downloads are off, ask the study owner.
  2. The transcripts, if the platform exports them. Default: sessions without a transcript are still searched for error dialogs, but a confused remark in them is reported only with a paraphrase marked NOT VERIFIED.
  3. What the round tested (the tasks or flows). Default: read the task list from the platform export if there is one; otherwise ask. It names the screens when grouping issues.
  4. Where the issues go. Default: issues.csv and clips in the working folder. Linear only when the user names the team; Slack only when the user names the channel.
  5. The Vivu project. Default: a new private project named "Usability ROUND" (ROUND is the round's name or date). Session recordings show testers' voices, faces and screens, and vivu_create_project makes a project visible to the whole organization unless visibility is private.

Files and state

Keep everything in one working folder on the user's computer:

usability-round/
  config.json        round name, tasks, destinations, Vivu project id
  state.json         per session: video_id, status; search job ids; checked moment keys; issues filed
  sessions/          the original recordings, videos only, no subfolders
  transcripts/       one transcript per session, named like the recording
  results/           each search result saved exactly as returned
  frames/            triage frames and contact sheets
  moments.csv        one row per checked moment
  issues.csv         one row per issue
  clips/             one clip per moment
  slack_message.txt  the summary message, before posting

state.json is written after every step. A rerun reads it and skips finished work: sessions already ready are not uploaded again, searches with a saved result file are not rerun, and a moment key (session file name plus the second it starts, such as checkout_s04.mp4@25) that is already in state.json is not added twice. Issues already filed keep their Linear ID. Run every command below from inside usability-round/, because the paths are relative to it.

Step 1: Check the Vivu connector and the setup

Goal: confirm every row of What you need before touching the recordings.

  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 it returns an account with can_create_projects: true, continue. If a later write call fails with "has not granted vivu.write", ask the user to reconnect Vivu and allow write access.
  2. Run ffmpeg -version and ffprobe -version. If either is missing, stop and ask the user to install ffmpeg.
  3. If the user wants Linear or Slack, list the Linear teams or read the Slack channel once to confirm access.

Done when the user has seen a short checklist with every requirement marked present or missing, and nothing required is missing.

Step 2: Measure the sessions and price the round

Goal: the user approves the index minutes and search credits before anything is uploaded.

A backlog of dozens of hours of sessions is far more than a monthly plan indexes, and old rounds test screens that have since changed. So this skill indexes one round (or one task across rounds) at a time.

  1. Copy the recordings into sessions/ and measure each one:
ffprobe -v error -show_entries format=duration -of csv=p=0 sessions/FILE

FILE is the recording's file name including its extension, such as checkout_s04.mp4. Run it once per recording. Sum the seconds and divide by 60: that is the index minutes this round uses. 2. Call vivu_get_usage for the user's plan and what remains this month. 3. Work out search credits. Each round runs the two precise searches in Step 4 once, however many sessions it holds. A precise search uses 5 credits and a fast search uses 1 credit (this skill runs no fast searches), so a round is about 10 credits (estimate; add 5 for every search rerun). 4. Show one table and wait for a yes:

This round Remaining this month Free plan Premium plan ($30 a month)
Index minutes sum of the ffprobe durations from vivu_get_usage 20 a month 180 a month
Search credits estimate from item 3 from vivu_get_usage 50 a month 500 a month

If the round does not fit, offer these levers in order: index only the sessions for the task the team is deciding on now, then split the round across two months, then a larger plan. Do not trim sessions to save minutes; the stuck moment is often near the end of a task.

Done when the user has approved the round, and config.json lists the sessions and their durations.

Step 3: Create the project and upload

Goal: every session in the round shows ready in Vivu.

Before this step, ask the user to confirm that the testers agreed to their recordings being analyzed with a third party tool (see Compliance).

  1. Call vivu_list_projects and reuse the round's project if one exists. Otherwise call vivu_create_project with name "Usability ROUND" and visibility "private". Record the project ID in config.json.
  2. Call vivu_open_upload_page with the project ID. It returns upload_url, a one time sign in link that expires in 180 seconds, so request it only when the user is ready, hand it over at once, and never store or post it.
  3. The user opens upload_url in their own browser and picks the files from sessions/. If a browser tool that can attach local files is available, it can do this instead; Claude in Chrome accepts at most 10 MB per upload call, and most session recordings are larger, so those go in through the user's browser or the Vivu web app. Never split or recompress a recording to make it fit.
  4. Vivu replaces spaces and brackets in file names with underscores. Match Vivu's file names back to sessions/ after making the same replacement.
  5. Poll vivu_list_videos about every 30 seconds until every video shows ready. Record each video_id in state.json.

In our test run the files were uploaded without a browser, so the browser upload itself was not exercised in our test run.

Done when every session in config.json has a video_id in state.json and vivu_list_videos shows it ready.

Step 4: Run the two searches

Goal: candidate time ranges for confused remarks and error dialogs, saved as returned.

Field Query Mode maximum_results
said_confused (main output) the tester says out loud that they are not sure what something means or asks where something is precise 20
error_shown (main output) an error message pops up in a dialog box on the screen precise 20

Why these two, in this order: the first finds the problems testers put into words, with a time to look at. The second flips from what was said to what was shown, and catches the errors nobody mentioned. Together they cover talking testers and silent ones, as long as something went visibly wrong or someone spoke up. Both are precise, because only precise returns time ranges; fast returns whole files and is for picking files in a large project, which one round does not need.

maximum_results is also the ceiling on how many ranges come back. A round of five to ten sessions rarely has 20 confused remarks or 20 error dialogs; if either search returns exactly 20, the ceiling was hit, so rerun it per group of sessions or with a higher value (the tool accepts 1 to 100).

Run each query with vivu_search_videos (project_id, query, mode, maximum_results). 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 returned in results/FIELD.json. Show the Vivu result page link in the reply; it expires after four hours, so it never goes into issues.csv, moments.csv, state.json, Linear or Slack.

If the team's product uses words other than "error" for failures (a toast, a banner, a red inline message under a field), add a third query in their words and mark it as a candidate query: it was not exercised in our test run.

Done when both result files are saved and the user has seen the ranges listed per session, marked as candidates.

Step 5: Check every moment

Goal: every range confirmed or rejected against the recording, with the false positives counted.

  1. Error ranges. Extract three frames (start, middle, end) and look at each one:
ffmpeg -v error -ss SECONDS -i sessions/FILE -frames:v 1 -q:v 3 frames/FIELD_hN_mid.png

SECONDS is a time in the range, FIELD the query field, N the result number. A range where no frame shows an error dialog is a false positive. Read the dialog title and message from the frame, not from the reason text. The first frame of a range often shows the page before the dialog appears, which is useful: it shows what the tester did just before. 2. Confused remarks. Read the transcript for the range and find the sentence. Then call vivu_get_video_summary with project_id, video_id, include_segments: true, and start_ms and end_ms around the range, as a second signal. The transcript decides: a section summary can leave a remark out, and the reason text paraphrases, so neither is quoted. A range with no confused sentence in the transcript is a false positive. Without a transcript, keep the moment as a candidate marked NOT VERIFIED. 3. One range can hold two remarks or two dialogs. Record each one as its own moment. 4. Write moments.csv, one row per checked moment:

moment_key,session_file,start_s,end_s,signal,verified_by,frame_files,note
checkout_s04.mp4@25,checkout_s04.mp4,25.1,28.6,said_confused,transcript,frames/sheet_said_confused_h3_02.png,"Checkout: cannot find where to enter a promo code"
  1. Count false positives per search and show them to the user with the confirmed moments. If fewer moments are confirmed than the user expected, report the real number.
Worked example from our test run

We used five synthetic session recordings (the longest 90 seconds, the shortest 46 seconds, 4.96 minutes in total), built with a script that logs the true time of every remark, dialog and pointer movement. Two sessions had think aloud narration and three had none. The narration never mentioned the error dialogs, and no confused wording appeared on screen, so each search could only succeed through its own signal. Look alikes were planted: neutral remarks ("I will call it Test Lab"), success dialogs, a neutral confirmation dialog and a dropdown menu.

Three of the sessions were indexed the day before; the two new ones used 2.47 index minutes and were ready about 1.3 minutes after the upload started. The two searches used 10 search credits (estimate).

The said_confused search returned 4 ranges: 4 real, 0 false, 0 missed against the five remarks we scripted. One 22 second range held two remarks and its reason named only one of them. The ranges had a median width of 10 seconds. None of the neutral remarks came back, and nothing came back from the sessions without narration.

The error_shown search returned 5 ranges: 5 real, 0 false, 0 missed. The reason text read each dialog title correctly. None of the success dialogs, the confirmation dialog or the dropdown came back. The session with no narration at all, which isolates the screen signal, had both of its error dialogs found. The ranges had a median width of 14 seconds and began a few seconds before the dialog appeared.

In our test run the section summary for the last part of the longest session covered several pages in one section and left out one confused remark and one error dialog, which is why the transcript decides.

Done when every range is marked real or false in moments.csv, and the user has seen the counts.

Step 6: Look for hesitation around each moment

Goal: a note on each moment saying whether the pointer showed hesitation, marked as a candidate.

A tester who circles a button without clicking is stuck, but Vivu's search for pointer movement did not hold up in our test run. Across three wordings of a hesitation search, each tuned on the same test corpus, 25%, 60% and 33% of the returned ranges were false. Every false range showed a pointer resting still or making one straight move, and the reason text described circling that the frames did not show. In two of the five false ranges the tester was talking about looking for something, and the search treated those words as pointer movement. So this skill does not search for hesitation. It looks at the pointer only near moments already confirmed in Step 5, where a person can judge it.

  1. For each confirmed moment, build a contact sheet from 5 seconds before the range to 5 seconds after it. Each tile is one frame, half a second apart, 42 tiles per sheet:
ffmpeg -v error -ss START -t LENGTH -i sessions/FILE -vf "fps=2,scale=320:-1,tile=6x7" frames/sheet_FIELD_hN_%02d.png

START is the range start minus 5 (not below 0), LENGTH the range length plus 10, in seconds. Keep -t before -i so the sheets stop where asked. Tile k (counting from 0, left to right, top to bottom, continuing into the next sheet) is at START + k x 0.5 seconds. 2. Look for the pointer moving back and forth over one control or area for a few seconds without a click, or hovering between two options. A pointer resting still is not hesitation; a tester may be reading. 3. Write what you saw into the moment's note, starting with "candidate:", and the time span. Never open an issue from a contact sheet alone.

In our test run the sheets showed the pointer going back and forth between two plan cards after a confused remark, and circling a form field after an error dialog was closed; both matched the scripted hesitations. Hesitation far from any remark or error was not covered, because no sheet reaches it. A silent tester who never hits an error can be stuck without this skill noticing.

Done when every confirmed moment has a hesitation note (a candidate description or "none seen").

Step 7: Group into issues and cut clips

Goal: issues.csv with one row per problem and a clip for each moment.

  1. Group moments into issues by screen and by what went wrong. The same error on the same screen in two sessions is one issue with two moments. A remark and an error on the same screen can be one issue when they describe the same problem; say so in the title.
  2. Write each title as the problem a designer would fix, in plain words ("Checkout has no promo code field"), not as the tester's words.
  3. Cut one clip per moment, starting 5 seconds before it and lasting 15 seconds, with re-encoding so the clip starts exactly where asked:
ffmpeg -v error -ss START -to END -i sessions/FILE -c:v libx264 -c:a aac clips/ISSUE_STEM_MMSS.mp4

START is the moment's start minus 5 (not below 0), END is START plus 15. ISSUE is the issue ID (UT-1, UT-2, ...), STEM the file name without extension, MMSS the moment's start as minutes and seconds. 4. Before writing every row, show the user one row and this field mapping, and ask whether it looks right:

issue_id,title,screen,signals,sessions,moments,clip_files,hesitation_note,status
UT-1,Testers cannot tell the Team and Business plans apart,Plan picker,said_confused,1,1,clips/UT-1_onboarding_s02_0013.mp4,"candidate: pointer moves back and forth over the two plan cards before choosing",draft
Issue field Comes from If unavailable
title Claude's reading of the moments in the group ask the user
screen the page shown in the frames UNCERTAIN
signals which searches confirmed the moments none
sessions, moments counts from moments.csv none
clip_files Step 7 item 3 say which clip failed
hesitation_note Step 6, always a candidate "none seen"

The title and the grouping are Claude's judgment. If a grouping is wrong, two different problems end up in one ticket, which is why the user checks the sample first.

In our test run the confirmed moments grouped into issues by screen, two card payment errors from different sessions became one issue, and every clip came out at the requested length.

Done when issues.csv and moments.csv are written, every moment has a clip in clips/, and the user has approved the sample row and the mapping.

Step 8: File the issues in Linear and notify Slack

Goal: the issues in Linear and one summary in Slack, only if the user asked for them.

Creating issues and posting a message act as the user. Name the Linear team and the Slack channel, show one complete issue and the complete Slack message as they will appear, and wait for an explicit yes.

Issue template:

Title: TITLE
Labels: usability
Seen in N of M sessions from the usability round of DATE.

What happened: WHAT THE MOMENTS SHOW, in plain words. Quotes only from the transcript.
Pointer: HESITATION NOTE (candidate, read from a contact sheet), or leave out.

Moments:
- SESSION_FILE at MM:SS (said, checked against the transcript)
- SESSION_FILE at MM:SS (error dialog "DIALOG TITLE", checked in frames)

Clip: CLIP_FILE (attached)

Slack message:

Usability review, DATE: N sessions, K issues drafted in Linear

Said out loud
- UT-1 TITLE LINEAR_LINK

Error on screen (nobody said anything)
- UT-6 TITLE (2 sessions) LINEAR_LINK

Not covered: stuck moments where a tester neither spoke nor hit an error.

Sources in issues are session file names plus MM:SS, never Vivu result links, which expire. If the Linear connector cannot attach a local video file, say so and offer two options: create the issues without the clip and have the user drag the clips in, or keep the working folder as the deliverable. Record each created issue's ID in state.json so a rerun does not file it twice.

This step was not exercised in our test run: the issue and the message were rendered to files and not sent.

Done when the user has approved the sample issue and message and they exist in Linear and Slack, or the user has chosen the local files instead.

Compliance

  1. Consent of the people recorded. Testers agreed to be recorded for research, but not always to their recording being uploaded to a third party analysis tool. Before Step 3, ask the user to confirm the consent covers this; if unsure, ask the research lead first.
  2. Minors. If any tester is under 18, stop and ask whether a guardian consented to this use; without that, do not index those sessions.
  3. Personal data on screen. Sessions show testers' names, emails and sometimes payment details typed into forms. Clips attached to Linear are visible to everyone on that Linear team; before Step 8, look at each clip's frames and tell the user which ones show personal data.
  4. Where the videos go. Uploading puts the recordings in a Vivu project in the user's account until they delete it. The project is private in this skill because the organization default makes it visible to every member. The skill never deletes anything on its own; if the user asks to remove the recordings afterwards, confirm first, because vivu_delete_video and vivu_delete_project are permanent.
  5. The skill does no face, voice or identity recognition. Issues name sessions by file name, never by the tester's name.
  6. Creating Linear issues and posting to Slack act as the user and need approval of a complete sample first (Step 8).

Known failure modes

Symptom Cause Fix
(observed) one range holds two confused remarks and its reason names only one Vivu returns a range around nearby moments, not each remark read the transcript for the whole range and record each remark as its own moment
(observed) a section summary does not mention a remark the transcript has summaries of long stretches merge several pages into one section check remarks against the transcript; use the summary only as a second signal
(observed) the first frame of an error range shows the page before the dialog appears ranges start a few seconds early use the middle frame to confirm the dialog; use the first frame to see what the tester did just before
(observed) a hesitation search returned a range where the "pointer rests still while the tester asks where the promo code goes" pointer movement search takes cues from the narration do not search for hesitation; read the pointer on contact sheets around confirmed moments (Step 6)
(observed) the reason text says the pointer "moves in small circles" while the frames show it still the reason describes motion it did not see never report pointer movement from the reason text; only from frames
a silent tester was clearly stuck but no issue mentions it neither search covers a tester who says nothing and sees no error say this limit in the Slack summary; watch those sessions in full if the task matters
a search returns exactly as many ranges as maximum_results the ceiling was hit rerun per group of sessions or with a higher maximum_results
an empty result for a session that clearly has an error visual search can miss moments; an empty result does not prove there were none build contact sheets across the task where the error should be
a confused remark has no transcript to check against the platform export had no transcript keep it as a candidate marked NOT VERIFIED; quote nothing
"has not granted vivu.write" Vivu connected read only the user reconnects Vivu and allows 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 the user opens it
a file is rejected by the browser upload tool Claude in Chrome accepts at most 10 MB per upload call the user adds that file in the Vivu web app; do not split or recompress it
a result's file name does not match any file in sessions/ Vivu replaced spaces and brackets with underscores make the same replacement in the local names before matching

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.