SkillsSkill for Claude

Incident timeline from a war room call

Give Claude the recording of an incident bridge call, its transcript, the time the recording started and the incident channel's message times, and get back a timeline table for the postmortem: every moment someone shared a monitoring dashboard, ran a rollback, failover or traffic shift command in a terminal, or said a decision out loud, with the wall clock time, the dashboard values or exact command read from a full frame, and the words from the transcript. The transcript only says "Okay, running it." and channel messages often lag the screen, so which dashboard was up and when the command really ran exist only in the screen share.

Maintained by Vivu. Updated 2026-10-02.

Download

incident-war-room-timeline.zip

9 KB. Unzips to incident-war-room-timeline/SKILL.md. Upload the zip as it is in the Claude app, or unzip it into your skills folder for Claude Code.

SHA-256 2f83a90bfd618c503f2ea1b52207c855766814dbde39bd69cf0163e0e8565389

At a glance

What the Incident timeline from a war room call skill does, where it runs, what it needs, and when it asks
Looks forThree kinds of moments: a monitoring dashboard shared on screen, a rollback, failover or traffic shift command typed and run in a terminal, and a decision said out loud. The first two are only in the picture, so every dashboard value and command is read from a full frame of your recording, and every decision is checked against the transcript, before it goes into the table.
Runs onClaude Code on your computer (terminal or the Code tab of Claude Desktop), because it cuts and reads frames from the local recording with ffmpeg. No residential IP is needed and nothing is scheduled.
Needs
  • The Vivu connector with write access, to create a private project, upload and search
  • ffmpeg and ffprobe, to cut the recording, measure minutes and extract frames
  • The bridge recording as a local mp4, because frames come from your own file
  • The transcript with timestamps, because decisions and quotes come from it, not from Vivu's reason text
  • The time the recording started in UTC, to turn offsets into wall clock times
  • The incident channel's key messages with times, to pick which stretches of a long call to index
  • A browser that can open the Vivu upload page, because the connector has no direct upload tool
Your Vivu planIndexes only the stretches of the call picked from the channel messages, plus three precise searches. The skill shows the minutes and a credit estimate against your plan before it uploads anything. In our test run 3 synthetic recordings were 4.69 minutes in total.
Asks you firstUsing the recording (consent and permission to upload), the cut windows, the indexing minutes and credit estimate, and the sample rows before the full table.

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 internal meetings recorded under your company's policy, where people knew they were recorded.
  • Bridge calls can show secrets, tokens or customer data; the Vivu project is created private and such frames are flagged SENSITIVE and kept out of the postmortem.
  • The recording stays in your Vivu project until you delete it.
  • Vivu's results are candidates; reading small terminal text and dashboard numbers is the weakest step, so commands and values come only from full frames, never from the reason text.
  • Tested only on clean synthetic screens; real calls with small fonts, scrolling output or many windows were not tested.
  • Claude in Chrome uploads at most 10 MB per call; larger files go through the Vivu web app.
  • The table records what was shown, run and said; it does not name a root cause or rate anyone's actions.

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:

Build the postmortem timeline from our incident bridge recording: bridge.mp4 and bridge.vtt are in ~/incidents/INC-2207, the recording started at 14:02 UTC, and here are the channel messages.

In Claude Code you can also type /incident-war-room-timeline. 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 collect the inputs
  8. Step 3: Pick the windows from the channel and cut
  9. Step 4: Price the indexing and get approval
  10. Step 5: Upload and index
  11. Step 6: Search the three kinds of moments
  12. Step 7: Check every hit
  13. Step 8: Convert to wall clock and assemble the timeline
  14. Compliance
  15. Known failure modes

The full skill

This is incident-war-room-timeline/SKILL.md from the download, as Claude reads it: the frontmatter first, then the instructions.

---
name: incident-war-room-timeline
description: "Turn a recorded incident bridge call into a postmortem timeline with Vivu: dashboard shares and rollback commands read from frames, spoken decisions from the transcript, in wall clock time."
---

Incident timeline from a recorded war room call

This skill takes the recording of an incident bridge call (a Zoom, Google Meet or Teams meeting where people shared dashboards and terminals while they worked the incident, exported as mp4 with its transcript), the time the recording started, and the incident channel's message times, and returns a timeline table for the postmortem. Each row is one moment of three kinds: someone shared a monitoring dashboard, someone ran a rollback, failover or traffic shift command in a terminal, or the incident lead said a decision out loud. Each row has the wall clock time, the offset in the recording, the dashboard title and values or the exact command read from a full frame, the path of that frame, the words from the transcript, and an empty "for postmortem" column for the person writing it up. Claude uses the channel times to cut the recording down to the few stretches that matter, prices the indexing against the user's Vivu plan, indexes the cuts in a private Vivu project, runs one search per kind of moment, checks every hit against frames or the transcript, and converts the times to wall clock.

The value is in what only the screen share shows. A bridge call transcript says "Can everyone see my screen?" and "Okay, running it."; which dashboard was up, what the error rate read, and which command was run exist only in the picture. Channel messages are often posted minutes after the command actually ran, because people run the command first and type the message later, so the channel cannot give the time something happened. Decisions are the other way around: they are spoken on a camera grid with nothing on screen. So the skill searches the screen for dashboards and commands, searches speech for decisions, and reads every command and value from a full frame of the user's own recording before it goes into the table.

When to use

Use when an SRE, on call lead or incident commander says "build the timeline for the postmortem from the bridge recording", "when exactly did we run the rollback, the channel says 14:11 but I think it was earlier", "which dashboards did we look at during the incident", or "pull the decisions out of the war room recording". For one question about one moment ("when did she share the DB graph?"), search Vivu directly. For release demos in sprint reviews, use a release notes screenshot skill instead. This skill does not find the root cause and does not judge anyone's actions; postmortems here follow the blameless convention, and the table only records what was shown, run and said.

Working principles

  1. Report measured numbers, not estimates. When a number is an estimate, say so.
  2. Vivu's results are candidates. A row is verified only after a full frame shows the dashboard or command (screen rows) or the transcript has the decision (decision rows). 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 transcript, no recording start time, 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 cut windows before upload, the indexing cost before upload, and the sample rows before the full table.
  5. Record what happened; never assign blame or root cause. Commands and values are copied from the frame, never paraphrased.

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 recording cut the windows, measure minutes, extract frames ffmpeg -version and ffprobe -version
The bridge recording as a local mp4 (downloaded from Zoom, Google Meet or Teams) cuts and frames come from the local file; Vivu has no export tool ls BRIDGE_FOLDER
The transcript with timestamps (the meeting tool's VTT or SRT export, or the output of a local speech to text tool) decision rows and quotes come from it, never from Vivu's reason text ls BRIDGE_FOLDER for a .vtt or .srt
The time the recording started, in UTC every wall clock time is that start plus the offset the meeting tool's recording list, or ask the user
The incident channel's messages with times (export or pasted) to pick which stretches of a long call to index ask the user to paste the key messages
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 (terminal or the Code tab of Claude Desktop). It downloads nothing from YouTube, so no residential IP is needed. Nothing is scheduled and nothing is written outside the working folder.

Inputs to collect

Ask for anything missing, most important first.

  1. The recording file and its transcript (BRIDGE_FOLDER). Required.
  2. The recording start time in UTC (REC_START). Required; ask if the meeting tool does not show it.
  3. The channel messages that mark the key moments (alert, mitigation, recovery). Required for calls longer than about 20 minutes; for a short call the whole recording can be indexed.
  4. Which systems were involved (service, database, region names). Default: taken from the channel messages. They help read the frames, not the searches.
  5. The Vivu project name. Default: "Incident INCIDENT_ID", private.

Files and state

Keep everything in one working folder next to the recording:

incident-timeline/
  windows.csv            cut file, CUT_START, CUT_END, minutes, the channel messages that chose it
  cut/                   the cut stretches of the recording, the files that get uploaded
  results/               raw search results, one JSON file per search
  frames/                contact sheets and full frames read for each row
  incident_timeline.csv  one row per verified or candidate moment
  rejected.csv           candidates that failed a check, with the reason
  state.json             uploaded files and video ids, searches 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, searches already run are not rerun, and checked hits keep their verdicts, so an interrupted run resumes where it stopped.

Step 1: Check the Vivu connector and the setup

Goal: every row of What you need is confirmed before anything is cut or 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 BRIDGE_FOLDER and check that the recording has a transcript.
  3. Create the working folders; ffmpeg does not create an output folder:
mkdir -p incident-timeline/cut incident-timeline/results incident-timeline/frames

Run every later command from inside incident-timeline/ (cd incident-timeline).

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

Goal: the user has confirmed the recording may be used and Claude has REC_START and the channel messages.

  1. Ask Compliance items 1 and 2 before anything else in this step. Stop if the recording fails them.
  2. Get REC_START. Check it against one known moment: a channel message like "bridge is up" should land a little after the recording's first speech, never before it.
  3. Collect the channel messages with their times.

In our test run the recordings were made for the test and their start times were set in advance, so this step was not exercised in our test run.

Done when the user has confirmed consent and REC_START, and the channel messages are in windows.csv notes.

Step 3: Pick the windows from the channel and cut

Goal: a few cut files that cover the moments the timeline needs, so index minutes go only where they count.

  1. Group the channel messages into stretches (alert and first look, mitigation, recovery). For each, set the window from about five minutes before the first message to a few minutes after the last. Channel messages lag the screen, so the margin goes mostly before the message. Aim for 3 or 4 windows of 10 to 15 minutes; merge windows that overlap.
  2. Convert each window to seconds in the recording (message time minus REC_START), show the windows to the user and let them adjust.
  3. Cut with re-encoding, so the cut starts exactly at CUT_START and every time Vivu returns maps back by adding CUT_START (RECORDING_FILE is the original file; N is the window number):
ffmpeg -v error -ss CUT_START -to CUT_END -i RECORDING_FILE -c:v libx264 -c:a aac cut/window_N.mp4

A stream copy (-c copy) is faster but starts at the nearest keyframe, a few seconds early, and every time in the table is then off by an unknown amount.

In our test run both narrated recordings were cut this way from a simulated channel log, and the times in the table were mapped back by adding CUT_START.

Done when cut/ holds one file per window and windows.csv records each CUT_START.

Step 4: Price the indexing and get approval

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

  1. Measure each cut file and sum the minutes. ffprobe takes one input file per call:
ffprobe -v error -show_entries format=duration -of csv=p=0 cut/window_N.mp4
  1. Call vivu_get_usage for the plan and what remains this month.
  2. Search credits: three precise searches (dashboard, command, decision), 5 credits each, plus 5 for each rewording if a first page is not clean. Label the total as an estimate.
  3. Show one table and wait for approval:
This incident 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, a whole 90 minute bridge call is half of Premium and does not fit Free, while four 12 minute windows are about 48 minutes, and Free has room for one window. If the windows still do not fit, offer these levers in order: tighten the windows around the channel messages, drop the window the user cares least about (say which), and only then a larger plan.

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 5: Upload and index

Goal: every cut file 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". Bridge calls show production systems, internal hostnames and sometimes customer data or secrets; 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 or file. Give it to the user to open in their own browser and choose the files in cut/, or attach them with a browser tool that can upload local files. Claude in Chrome accepts at most 10 MB per upload call; larger files the user adds 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 windows.csv by file name; Vivu turns spaces and punctuation in names into "_". 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 windows.csv as ready.

Step 6: Search the three kinds of moments

Goal: one raw result file per kind of moment.

Run each query with vivu_search_videos (project_id, query, mode "precise", maximum_results 15). 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. Show the result page link in the live reply only; it expires after four hours, so it never goes into the table or any file.

Field Query Mode maximum_results
dashboard someone shares their screen showing a monitoring dashboard with graphs of error rate, latency or connections over time precise 15
command someone types a rollback, failover or traffic shift command into a terminal on the shared screen and runs it precise 15
decision the incident lead says out loud that the team has decided to roll back, fail over or escalate, as a decision rather than a suggestion precise 15

All three are precise because the table needs time ranges; a fast search returns only whole files, and the windows are already chosen. maximum_results 15 is more than a few windows usually hold of each kind, and it is the ceiling on what comes back: a list that stops at exactly 15 means the cap was hit, so raise it and rerun that field.

Why this chain: the dashboard search finds what the team was looking at, the command search finds what was done on screen, and the decision search flips from the screen to speech to find why, which is never on screen. The last clause of the decision query ("a decision rather than a suggestion") is there because bridge calls are full of "should we fail over?" that is not a decision.

Done when results/ holds the three result files and state.json records the job IDs.

Step 7: Check every hit

Goal: every hit has a verdict and every screen row has a value read from a full frame.

Vivu returns a time range that contains the moment, not the exact second, and the reason text is a paraphrase. In our test run the reason quoted every command correctly, but it also wrote "roll check out back" for a spoken "roll checkout back"; commands, values and quotes in the table come from frames and the transcript only. Reading small terminal text and dashboard numbers is the weakest part of this skill: other tests found the reason inventing small text and digits, and a contact sheet small enough to scan is too small to read a terminal.

  1. Dashboard and command hits: 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 8x5 grid holds 20 seconds, so for a longer window raise the second number):
ffmpeg -v error -ss START -t DURATION -i cut/window_N.mp4 -vf "fps=2,scale=320:-2,tile=8x5" -frames:v 1 frames/FIELD_HIT_sheet.png

HIT is h plus the hit's number within the field (h1, h2, ...). Keep the quotes around the filter. Windows usually start and end on the neighboring screen, so find the first cell that shows the dashboard, or for a command the first cell where the command's output appears, and use that cell's time (START plus half a second per cell before it). 2. Extract that moment as a full frame (SECONDS is the cell's time) and read it:

ffmpeg -v error -ss SECONDS -i cut/window_N.mp4 -frames:v 1 -q:v 3 frames/FIELD_HIT_read.png

For a dashboard, copy the dashboard title and the panel titles and values that matter. For a command, copy the command line exactly and its output line. When the mouse pointer covers part of the text, read a neighboring cell or the output line, and mark the field UNCERTAIN if neither settles it. Reject the hit when the frame is a document or a page that only contains a command (a runbook, a wiki, a chat message), when the command is diagnostic only (listing pods, reading logs), or when the screen is not a monitoring dashboard (a status page editor, a ticket). 3. If the frame shows a secret, a token, a password or customer data, keep the row but set flag SENSITIVE; that frame never goes into the postmortem document. 4. Decision hits: read the transcript lines inside the window. The hit is verified only if someone states a decision ("we are making the call", "decision: we roll back"), not a question or a proposal. Read vivu_get_video_summary with include_segments, start_ms and end_ms around the window as a second signal only. 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 3 synthetic recordings, 4.69 minutes in total after cutting, made for the test: a meeting app frame with monitoring dashboards, terminals where commands were really typed in a small monospace font, a wiki runbook page, a status page editor and a camera grid. Each narrated recording had its own synthetic voice; the narration never named a dashboard, a metric or a command ("Can everyone see my screen?", "Okay, running it."). The third recording was a silent control with the same kinds of screens and no audio. Before searching we wrote down every target and every distractor: diagnostic commands in the same terminal, the runbook page showing the exact rollback command in a code block, a status page editor shared on screen, a speaker saying they were watching the graphs with nothing shared, and a spoken "Should we fail over to west? Maybe. Let's not decide yet." From the upload to all 3 recordings ready took 1.3 minutes.

The dashboard query returned 5 moments: 5 real, 0 false and 0 missed. The command query returned 4: 4 real, 0 false and 0 missed. The decision query returned 2: 2 real, 0 false and 0 missed. This was the first wording of each query on this corpus. None of the distractors came back, and the silent control's dashboards and commands were all found, so those hits came from the picture. Command windows were about 16 seconds wide, several times longer than the typing, and every screen window began or ended on the neighboring scene, so the sheet, not the window, gives the time. Every command and dashboard value was read correctly from a full frame; on the contact sheet only the large dashboard numbers were readable. These were clean synthetic screens; real bridge calls with smaller terminal fonts, scrolling output, several windows on one screen, cross talk and a full length call were not exercised in our test run.

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

Step 8: Convert to wall clock and assemble the timeline

Goal: one table the incident lead can paste into the postmortem.

  1. For each verified or candidate moment: wall clock = REC_START + CUT_START + the moment's seconds in the cut file (the sheet cell for screen rows, the transcript line's start for decisions). offset_mmss is CUT_START plus those seconds, written as minutes and seconds into the full recording.
  2. Write the rows in time order:
wall_clock_utc,recording_file,offset_mmss,category,what_read_from_frame,frame_path,quote_from_transcript,quote_source,status,flag,for_postmortem
14:10:40,RECORDING_FILE,00:40,decision,,,"Okay. Decision: we roll checkout back to yesterday's release, right now. I will take it.",meeting transcript,verified,,
14:11:12,RECORDING_FILE,01:12,command,"kubectl rollout undo deployment/checkout-api -n prod -> deployment.apps/checkout-api rolled back",frames/command_h1_read.png,"Okay, running it.",meeting transcript,verified,,
  1. Field mapping:
Field Source If unavailable
wall_clock_utc REC_START + CUT_START + seconds in the cut UNCERTAIN when REC_START was guessed
recording_file the original file name from windows.csv none
offset_mmss CUT_START + seconds in the cut none
category dashboard, command or decision none
what_read_from_frame dashboard and panel titles and values, or the command and its output line, from the full frame UNCERTAIN
frame_path the full frame blank for decisions
quote_from_transcript the transcript lines at that moment, word for word NOT VERIFIED
quote_source meeting transcript or local speech to text none
status verified when the full frame shows the dashboard or command (screen rows) or the transcript has the decision (decision rows) candidate when that check could not be made
flag SENSITIVE when the frame shows a secret, token or customer data blank
for_postmortem left empty for the person writing the postmortem 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 cell chosen as "the command ran" is the first cell where its output appears, and whether a sentence is a decision is Claude's reading of the transcript.
  2. Write incident_timeline.csv and rejected.csv. Give the user the counts per category and, where a channel message exists for the same event, the gap between the channel time and the screen time, without comment on who posted it.

In our test run the table had a row for each checked hit; the silent recording's screen rows were verified from full frames and their quote_from_transcript was NOT VERIFIED, because it had no audio. The user's approval of the sample rows was not exercised in our test run.

Done when incident_timeline.csv exists with a row for every verified or candidate moment and the user has approved the sample rows.

Compliance

  1. Use only internal meetings recorded under the company's recording policy, where the people on the call knew it was recorded. Ask before Step 2 and stop if the recording does not meet this.
  2. Bridge calls show production systems, internal hostnames and sometimes customer data or secrets. Ask before Step 5 whether the company allows uploading this recording 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 that show secrets, tokens or customer data are flagged SENSITIVE and stay out of the postmortem document.
  4. The table records what was shown, run and said. It does not name a root cause and does not rate anyone's actions.
  5. No face, voice or identity recognition. Who spoke comes from the meeting tool's transcript labels or the user, not from Vivu.

Known failure modes

Symptom Cause Fix
(observed) a command window starts on the runbook page that shows the same command in a code block windows start a little before the moment and include the previous screen take the time from the first sheet cell where the command's output appears, and reject any hit whose only command is in a document
(observed) the reason writes "roll check out back" for a spoken "roll checkout back" the reason is a transcription with errors, not the transcript take quotes from the transcript only
(observed) the terminal text is unreadable on the contact sheet a sheet cell is too small for terminal text read the command from a full frame at the chosen cell
(observed) the mouse pointer covers part of the command in the full frame the presenter left the pointer on the line read a neighboring cell or the output line; mark UNCERTAIN if neither settles it
(observed) a summary segment titled "Executing Rollback" also covers the recovery dashboard that follows summary segments follow topics, not screens use segments only as a second signal; rows come from frames and the transcript
the reason reports a value or command that the frame does not show the reason can invent small text and digits never copy values or commands from the reason
a proposal ("should we roll back?") comes back as a decision speech searches find the topic, and a proposal is the same topic verify every decision against the transcript and reject questions and proposals
an empty result for a dashboard the user remembers an empty result does not prove it was not shared; it may be outside the windows, or a full screen chart with no title widen the window around the channel message, rerun, and say so in the table notes
a list stops at exactly maximum_results the cap cut the list short raise maximum_results and rerun that field
wall clock times are off by a constant amount REC_START is wrong, or the cut used -c copy confirm REC_START against a known moment and cut with re-encoding
"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

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.