SkillsSkill for Claude

Error triage from customer bug recordings

Give Claude a folder of screen recordings customers attached to support tickets, and it returns an issue table: one row per distinct error, with the exact error text read from a frame, the tickets and recordings it appeared in, the time in each, the page title and app version read from the screen, frames from before, during and after the error, a flag for frames with customer data, and an empty column for the engineer to confirm the steps to reproduce. Claude prices the indexing against your Vivu plan, indexes the recordings in a private Vivu project, runs one screen search per kind of failure, checks every hit on a sheet of frames, groups the hits by error text, and drafts one Linear issue per group after you approve a sample. The ticket says it crashed again; the error text, the page and the version are only on screen, often in a red toast that is gone in seconds.

Maintained by Vivu. Updated 2026-10-13.

Download

bug-video-error-issue-table.zip

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

SHA-256 4f005e580d2b30d42527de4a3531e6b9c2f8f240a30271d278d7f90a195528af

At a glance

What the Error triage from customer bug recordings skill does, where it runs, what it needs, and when it asks
Looks forMoments where an error dialog, a red toast or banner, or a sync failure notice is on screen, plus stuck spinners and blank pages as candidates, which ticket text and transcripts miss because customers rarely type the error and most recordings are silent. Every hit is checked against the source video before it reaches the table: a half second sheet of frames must show the failure, and the error text, page title and version are read from full frames, 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. The Linear connector is needed only to create issues at the end.
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, make frame sheets and read text from full frames
  • The recordings as local files with the ticket number in each file name, because frames come from them and Vivu has no export tool
  • A browser that can open the Vivu upload page, since the connector has no direct upload tool
  • The Linear connector with access to the target team, only if you want issues created
Your Vivu planIndexing uses Vivu index minutes for every recording you choose, and each kind of failure is one precise search at 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. Premium ($30 a month) has 180 index minutes; the Free plan with 20 index minutes a month fits only a short week of recordings.
Asks you firstIt asks you to confirm the recordings were submitted to support under your terms and that uploading them to a third party service is allowed, then asks before uploading (categories and searches, then minutes and the credit estimate against your plan), before writing the full table (sample rows and field mapping), and before creating anything in Linear (destination and one rendered issue).

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

  • Use only recordings customers submitted to support for troubleshooting; leave out anything sent for another purpose or showing minors.
  • Reading small on screen text is a weak Vivu capability and the search description can invent error text, so every hit is checked on a sheet of frames and the text is read from a full frame.
  • Stuck spinners and blank pages have no text to read; they stay candidates for an engineer to judge.
  • An empty search result does not prove no recording shows that failure.
  • Frames with customer names, emails, card numbers or keys are flagged and never attached to an issue.
  • Creating Linear issues acts as you; it happens only after you approve the team and a rendered sample.
  • 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.

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:

Here are this week's bug recordings from support tickets in RECORDINGS_FOLDER. Find every error popup and sync failure, read the exact error text, page and version, group the tickets by error, and draft Linear issues for the bug team.

In Claude Code you can also type /bug-video-error-issue-table. 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: Confirm consent and choose the categories
  8. Step 3: Price the indexing and get approval
  9. Step 4: Upload and index
  10. Step 5: Search each category and check every hit
  11. Step 6: Read the page and version before each error
  12. Step 7: Group by error text and confirm the sample
  13. Step 8: Create Linear issues after approval
  14. Compliance
  15. Known failure modes

The full skill

This is bug-video-error-issue-table/SKILL.md from the download, as Claude reads it: the frontmatter first, then the instructions.

---
name: bug-video-error-issue-table
description: "Turn customer bug screen recordings into a deduplicated issue table with Vivu: find error popups and sync failures, read the exact error text, page and version, then draft Linear issues."
---

Error screen triage from customer bug recordings

This skill takes a folder of screen recordings that customers attached to support tickets this week (phone or desktop recordings, usually silent, with the ticket number in the file name) and returns an issue table: one row per distinct error, with the exact error text read from a frame, the tickets and recordings it appeared in, the time in each recording, the page title and app version read from the screen, frames from before, during and after the error, a flag for frames that show customer data, and an empty column for the engineer to confirm the steps to reproduce. Claude measures the recordings, prices the indexing against the user's Vivu plan, indexes them in a private Vivu project, runs one screen search per kind of failure the support engineer cares about (error popups or red banners, sync failure notices, and optionally spinners that never stop and blank pages), checks every hit on a sheet of frames, reads the text from a full frame, groups the hits by error text, and writes issue_drafts.csv. After an engineer approves a rendered sample, it opens one Linear issue per group through the Linear connector.

The value is in what only the recording shows. The ticket says "it crashed again" or "can't save"; the error text, the code in it, the page the customer was on and the version in the footer exist only on screen, often in a small red toast that is gone after three or four seconds. A transcript has nothing to offer because most of these recordings have no voice. Vivu finds the moments a failure is on screen, and Claude reads every word of the error from a full frame instead of trusting the search result's description, so two tickets with the same error land in one issue and a green "saved" toast never becomes a bug.

When to use

Use when a support engineer or support QA lead says "go through this week's bug recordings and tell me which errors they show", "group these customer screen recordings by error message", "which tickets hit the same error", "read the error text and version from these videos and draft issues for engineering", or "find the recordings where the page just spins or goes blank". For one recording and one question ("what does the popup at the end say?"), open the file or search Vivu directly. For usability test sessions where the job is finding hesitation and confusion, use a usability test skill instead; for internal incident call recordings, use an incident timeline skill. This skill finds and reads errors; it does not judge what the customer did.

Working principles

  1. Report measured numbers, not estimates. When a number is an estimate, say so.
  2. Vivu's results are candidates. A moment reaches the table only after a sheet of frames shows the failure inside the window and the error text has been read from a full frame. Rejected candidates are counted and kept in rejected.csv with the reason.
  3. Stop and tell the user when a required capability or file is missing (no ffmpeg, no write access in Vivu, no Linear connector when issues are wanted). Do not guess around it.
  4. Ask the user before anything that is expensive to redo or that acts on their behalf: the failure categories and recordings before upload, the indexing cost before upload, the sample rows before the full table, and one rendered issue before anything is created in Linear.
  5. Find errors; never judge customers. The table has errors, pages and times, no comments on how the customer used the product.

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, make frame sheets, extract full frames ffmpeg -version and ffprobe -version
The recordings as local files, with the ticket number in each file name (for example ticket_48121.mp4) frames come from the local files, Vivu has no export tool, and the ticket column comes from the name ls RECORDINGS_FOLDER
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
Linear connector with access to the target team (only for Step 8) creating the issues list the team's issue labels once; if it is missing, the run ends with the CSV

The skill needs a shell and local files, so it runs in Claude Code on the user's computer (terminal or the Code tab of Claude Desktop). It downloads nothing from YouTube, so no residential IP is needed. Nothing is scheduled; the only write outside the working folder is the Linear step, after approval.

Inputs to collect

Ask for anything missing, most important first.

  1. The folder with this week's recordings (RECORDINGS_FOLDER), written as an absolute path, because every later command runs from inside bug-triage/. Required.
  2. The kinds of failure to look for. Default: error popups or red banners, and sync failure notices; add stuck spinners and blank pages only when tickets mention them, since those two have no text to read and stay candidates (Step 5).
  3. Whether issues should be created, and where. Default: no; the run ends with issue_drafts.csv. If yes, the Linear team and label (default label: bug).
  4. The Vivu project name. Default: "Bug recordings WEEK", private, where WEEK is the week's start date.
  5. How far back to look for the page before an error. Default: 5 and 10 seconds before the error.

Files and state

Keep everything in one working folder next to the recordings:

bug-triage/
  recordings.csv     file, ticket number, duration in seconds, Vivu video id
  results/           raw search results, one JSON file per category
  frames/            frame sheets, full frames used to read error text, page and version
  moments.csv        one row per checked hit, verified or rejected
  issue_drafts.csv   one row per distinct error text
  rejected.csv       candidates that failed a check, with the reason
  linear_issue.json  the rendered sample issue shown for approval
  state.json         uploaded files and video ids, searches run with job ids, every hit with its verdict, issues created

state.json is updated after every step. A rerun reads it first: files already uploaded are not uploaded again, searches already run are not rerun, checked hits keep their verdicts, and an issue already created for an error text is never created twice, so an interrupted run resumes where it stopped. Next week's run starts a new folder and a new project; to avoid reopening a known error, check the group's error text against the team's open issues before Step 8 creates anything.

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 RECORDINGS_FOLDER and write recordings.csv with each file and the ticket number taken from its name; tell the user about files with no ticket number.
  3. If issues are wanted, check the Linear connector by listing the target team's labels once.
  4. Create the working folder next to the recordings and move into it; ffmpeg does not create an output folder:
mkdir -p RECORDINGS_FOLDER/../bug-triage/results RECORDINGS_FOLDER/../bug-triage/frames
cd RECORDINGS_FOLDER/../bug-triage

Run every later command from inside bug-triage/, so frames/ and results/ resolve to the folders just created and RECORDINGS_FOLDER, being absolute, still points at the recordings.

Done when vivu_get_account shows can_create_projects: true, ffmpeg and ffprobe print versions, recordings.csv lists every file with its ticket number, and the working folders exist.

Goal: the user has confirmed the compliance items and approved the categories and their searches.

  1. Ask Compliance items 1 and 2 before anything else. Leave out any recording that fails them.
  2. Show the categories and their queries (the table in Step 5) and adapt the wording to the user's product only where it names something the product really shows (for example the integration name in the sync query). Describe what the failure looks like, not the exact words: a query that quotes an error message invites the search to quote it back on a frame that does not show it.
  3. Wait for a yes.

In our test run the recordings were made for the test, so the consent questions were not exercised in our test run.

Done when the user has confirmed consent and approved the categories.

Step 3: Price the indexing and get approval

Goal: the user sees the cost before anything is uploaded.

  1. Measure each recording and sum the minutes. ffprobe takes one input file per call, so run it once per file:
ffprobe -v error -show_entries format=duration -of csv=p=0 RECORDINGS_FOLDER/FILE

FILE is one recording's file name as listed in recordings.csv.

  1. Call vivu_get_usage for the plan and what remains this month.
  2. Estimate search credits: one precise search per category, plus one rewording per core category in case its first page is not clean. A precise search uses 5 credits in total. Label the total as an estimate.
  3. Show one table and wait for approval:
This run 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; Premium is $30 a month with 180 index minutes and 500 search credits. As an estimate, 20 recordings of 2 minutes each is 40 minutes, which fits Premium but is twice the Free allowance, while 4 categories cost 20 credits. If the recordings do not fit, offer these levers in order: index only the recordings whose ticket text mentions an error, a crash, a spinner or a blank page; index half this week and the rest next month; and only then a larger plan. Never drop a recording 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 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". Customer recordings show customer data; 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 never paste it into a message, a ticket or a file. Give it to the user to open in their own browser and choose the recordings, or attach them with a browser tool that can upload local files. Claude in Chrome accepts at most 10 MB per upload call; the user adds larger files in the Vivu web app. Never split or recompress a recording to fit.
  3. Poll vivu_list_videos about every 30 seconds until every file shows ready. Match each video back to recordings.csv by file name; Vivu turns spaces and punctuation in names into "_", so compare names with those characters replaced, or match on the ticket number. Record the video IDs.

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 recordings.csv as ready.

Step 5: Search each category and check every hit

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

These four queries ran in our test with these exact words. Keep the shape and change only what names the user's product:

Field Query Mode maximum_results
error_popup an error message appears on screen: a dialog box, a red toast or a red banner saying that an action failed, often with an error code precise number of recordings
sync_failed a notice on the page says that syncing with another app failed or that the connection to it expired precise number of recordings
spinner_stuck (candidates only) a loading spinner keeps turning in the middle of the page and the content never appears precise number of recordings
blank_page (candidates only) the whole page turns blank white after a click, with no menu, text or content left on screen precise number of recordings

Why this chain: the error and sync searches find when a failure message is on screen, the half second sheet confirms it and drops success messages, the full frame turns the picture into exact text, and the frames before the error (Step 6) give the page and version that the ticket never mentions. Most bug recordings are silent, so there is no spoken side to flip to; the flip here is from text on screen (error messages) to a state with no text (a spinner, a blank page), which is why those two stay candidates.

Run each query with vivu_search_videos (project_id, query, mode "precise", maximum_results equal to the number of recordings, at most 100). 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/CATEGORY.json. Show the result page link in the live reply only; it expires after four hours, so it never goes into the table, an issue or any file. All searches are precise because the table needs times; a fast search returns whole files only. maximum_results is set to the number of recordings because a recording usually shows one failure, and it is a ceiling on what comes back: a list that stops at exactly that number means the cap was hit, so raise it and rerun.

Vivu returns a time range that contains the moment, not the exact second, and the reason text is a paraphrase that can invent error text. Reading small or dense on screen text is a weak capability: small toasts held up in our test run on clean synthetic screens, while smaller type and real phone recordings were not tested. So the frames decide, never the search alone. Check every hit in this order:

  1. Is the failure on screen inside the window? Make a sheet of one frame every half second across the window (START is start_ms / 1000, DURATION is (end_ms - start_ms) / 1000; the 8x6 grid holds 24 seconds, so for a longer window raise the second number):
ffmpeg -v error -ss START -t DURATION -i RECORDINGS_FOLDER/FILE -vf "fps=2,scale=320:-2,tile=8x6" -frames:v 1 frames/CATEGORY_HIT_sheet.png

FILE is the recording the hit belongs to, matched from the result's file name to recordings.csv. HIT is h plus the hit's number within the category (h1, h2, ...). Keep the quotes around the filter. Find the cells where the failure is visible; a toast may be in only six to eight cells. Reject the hit as NOT_AN_ERROR when the only message is a success or neutral one (a green "saved" toast, a "sync complete" banner, a confirm dialog, a red status badge in a table), and as NOTHING_ON_SCREEN when no cell shows a failure. 2. Read the error text from a full frame at a cell where the message is fully visible (SECONDS is the window start plus half a second per cell before it):

ffmpeg -v error -ss SECONDS -i RECORDINGS_FOLDER/FILE -frames:v 1 -q:v 3 frames/CATEGORY_HIT_error.png

Copy the text word for word from that frame, including the code (ERR-402, Error 500) and any request ID. Never copy it from the reason text. If part of it is covered or too small to read, write what is legible and mark the rest UNCERTAIN. 3. A spinner or a blank page has no text to read. Keep those hits as candidates when the sheet shows the spinner turning or the page blank for the rest of the window, and say how many seconds it lasted; the engineer decides if it is a bug. 4. Look at every extracted frame for customer data: names, email addresses, card numbers, keys or tokens. Set sensitive_data_in_frame to yes for that moment so the frame is never attached to an issue. 5. Rejected hits stay in results/ and go into rejected.csv with the reason; they are counted, not dropped silently.

Worked example from our test run

In our test run we used 12 synthetic silent screen recordings of one accounting web app, 4.99 minutes in total, made for the test and named only by ticket number. Each error message appeared in a pair of recordings: an "Error 500" dialog, a small red toast in the top right corner, a red sync failure banner, and a small red toast at the bottom. The other recordings held only things that must not become bugs (a green "saved" toast, a green "sync complete" banner in the same spot as the failure banner, a neutral confirm dialog, red "Overdue" badges in a table, a blue news banner, a short spinner that finishes) or a failure with no text (a spinner that never stops, a page that turns blank). We wrote down every event before searching. From the upload to all recordings ready took 6.1 minutes.

The error_popup query returned 8 moments: 8 real, 0 false and 0 missed, with the first wording, and none of the success messages came back. The sync_failed query returned both sync failures (2 real, 0 false) and left out the green banner. Every error text, the code in it and the request ID were read from full frames, and the footer version was legible in every full frame we read; the search's reason text also quoted the errors correctly here, but the table never takes text from it. Windows were about 12 seconds wide (median) and started a few seconds before the message, so the sheet, not the window, gives the time. The spinner query returned 1 real and 1 false: the false one was the blank page recording, with a reason that described a spinner nobody could see in the frames. The blank page query found the blank page (1 real), but its window stopped while the page was still blank. The recordings were clean synthetic screens; phone recordings of a screen, heavy compression, scrolling, dark themes, smaller type and other languages were not exercised in our test run.

Done when every hit of every category has a verdict in state.json and the user has seen the real and rejected counts per category.

Step 6: Read the page and version before each error

Goal: for every verified moment, the page title and app version read from the screen, and the page the customer was on before the error.

  1. Extract one full frame 5 seconds before the error's first visible cell (BEFORE_SECONDS, never below 0). If that frame still shows the error or a page in transition, extract another 10 seconds before. For frame_after, extract one frame after the message is gone, with the same command. FRAME_SECONDS is the moment to extract and FRAME_NAME is before5, before10 or after:
ffmpeg -v error -ss FRAME_SECONDS -i RECORDINGS_FOLDER/FILE -frames:v 1 -q:v 3 frames/CATEGORY_HIT_FRAME_NAME.png
  1. Read the page title from the frame and the version from wherever the product shows it (a footer, an about panel, a settings page). A small footer version line was readable in full frames in our test run; when it is missing or illegible, write UNCERTAIN and say that the version has to be asked from the customer.
  2. Write the page before the error, the page title and the version into moments.csv.

In our test run the first frame before each error showed the page the customer was on and the version line every time; the earlier fallback frame and the after frame were not exercised in our test run. One sync failure was on the dashboard rather than on the integrations page, which is the kind of detail the frame before the error adds.

Done when every verified moment in moments.csv has a page title and a version, or UNCERTAIN with the reason.

Step 7: Group by error text and confirm the sample

Goal: issue_drafts.csv with one row per distinct error, approved by the user.

  1. First merge moments that are the same recording and the same time but came from two searches (a sync banner is also an error message), so each moment counts once. Then group verified moments by error text, keeping error codes and ignoring request IDs (two "Error 500" dialogs with different request IDs are one issue; "ERR-402" and "ERR-504" are two). Sync failures form their own group per integration. Spinner and blank page candidates form one group each, marked candidate.
  2. Build one row per group:
error_text,category,tickets,recordings,timestamps,page_title,app_version,frame_before,frame_error,frame_after,sensitive_data_in_frame,status,repro_steps_confirmed
"Payment failed: card_declined (ERR-402)",error_popup,"48133;48140","ticket_48133.mp4;ticket_48140.mp4","00:13;00:13","Billing | Billing · Update payment method","v4.12.3 build 2291 | v4.13.0 build 2317",frames/error_popup_h1_before5.png,frames/error_popup_h1_error.png,frames/error_popup_h1_after.png,yes,verified,
  1. Field mapping:
Field Source If unavailable
error_text read from the full frame in Step 5 UNCERTAIN for the illegible part
category the search that found it none
tickets the number in each file name the file name
recordings, timestamps file names and the first visible cell as MM:SS the window start, marked UNCERTAIN
page_title, app_version full frames from Step 6 UNCERTAIN
frame_before, frame_error, frame_after local frame paths blank
sensitive_data_in_frame yes or no from Step 5 check 4 yes when unsure
status verified, or candidate for spinner and blank page groups none
repro_steps_confirmed left empty for the engineer blank
  1. Show two or three sample rows and the mapping and wait for a yes before writing the full table. Say which parts are inferred: the grouping is Claude's reading of the error text, and the page before the error is a frame, not the customer's full path; if the grouping is wrong, two issues merge or one splits, and the engineer can move a ticket between rows.
  2. Write moments.csv, issue_drafts.csv and rejected.csv, and give the user the counts: groups, tickets per group, candidates rejected per category and why. When a category found nothing, say so; an empty result does not prove no recording shows it.

In our test run the moments grouped into one row per error message plus one candidate row each for the spinner and the blank page; the sync failures came back from both the error and the sync searches and were counted once. The user's approval of the sample rows was not exercised in our test run.

Done when issue_drafts.csv exists and the user has approved the sample rows.

Step 8: Create Linear issues after approval

Goal: one Linear issue per approved group, or a stop with the CSV.

  1. Render one issue from the first verified group and show it with the destination team and label:
{
  "team": "TEAM",
  "title": "Payment failed: card_declined (ERR-402) on Billing",
  "labels": ["bug"],
  "description": "Seen in 2 customer recordings this week.\n\nError text (read from the screen): Payment failed: card_declined (ERR-402)\nTickets: 48133, 48140\nPages: Billing; Billing · Update payment method\nVersions: v4.12.3 build 2291; v4.13.0 build 2317\nWhere: ticket_48133.mp4 at 00:13, ticket_48140.mp4 at 00:13 (local frames in bug-triage/frames)\n\nSteps to reproduce: not confirmed yet."
}

The description uses the customer's file names and times, never the Vivu result page link, which expires. Frames flagged sensitive are not attached. 2. Wait for explicit approval of the destination and the sample. Then create one issue per group with the Linear connector, skipping any group whose error text already has an open issue in that team, and record each issue ID in state.json.

Creating issues in Linear was not exercised in our test run; the sample issue was rendered to a file and nothing was sent.

Done when every approved group has an issue ID in state.json, or the user chose to stop with the CSV.

Compliance

  1. Use only recordings customers submitted to support under your terms of service, for troubleshooting. Ask before Step 2 and leave out anything else (recordings of other people's screens, recordings of minors, recordings sent for another purpose).
  2. Recordings show customer data. Ask before Step 4 whether the company allows uploading them to a third party service, and create the Vivu project as private. 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.
  3. Frames with customer names, email addresses, card numbers, keys or tokens are flagged and never attached to an issue; the issue names the file and time instead.
  4. Creating Linear issues acts as the user. It happens only after the user approves the destination and a rendered sample.
  5. The table describes errors, not customers. No face, voice or identity recognition; who sent a recording comes from the ticket.

Known failure modes

Symptom Cause Fix
(observed) the spinner search returns a blank page, and the reason says "the page goes blank with a loading spinner turning in the center" the reason describes what the query asked for, not what every frame shows judge spinners and blank pages from the half second sheet only; keep them as candidates
(observed) the window starts a few seconds before the error and runs well past it windows contain the moment, they do not mark its edges take the time from the first sheet cell that shows the message
(observed) the same sync failure comes back from the error search and the sync search both descriptions fit a red sync banner deduplicate by recording and time before grouping, and count the moment once
(observed) the blank page window ends while the page is still blank the window covers the change, not how long the state lasts for a candidate state, extend the sheet to the end of the recording and report how long it lasted
(observed) the cursor covers part of the message in the picked frame the customer was pointing at it pick a neighboring cell where the text is clear, or mark the covered part UNCERTAIN
(observed) frames behind an error show a card number or a customer's client names customers record their real screens flag sensitive_data_in_frame and never attach those frames to an issue
(observed) ffprobe stops with "provided as input filename, but" ffprobe takes one input file per call run ffprobe once per file
a green "saved" toast or a "sync complete" banner is reported as an error success messages share the position and shape of errors reject it as NOT_AN_ERROR on the sheet; never report a message whose text says it worked
the reason quotes error words that are not on the screen the reason text is a paraphrase and can invent on screen text copy error text only from a full frame
a toast is too small or blurry to read in a phone recording of a screen small type, compression or a camera pointed at a monitor read the clearest cell at full size; mark the unreadable part UNCERTAIN and ask the customer for a screenshot
a category comes back empty although tickets mention it an empty result does not prove no recording shows it look at the sheet of a recording the ticket names, reword once with what is really on screen, and report the real count
a list stops at exactly maximum_results the cap cut the list short raise maximum_results and rerun that category
"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 recordings.csv Vivu replaced spaces or punctuation in the name match on the ticket number in the name

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.