← WebMCP Directory

Tool tree

klipvia.miztton.com

Media & PersonalTools verified
Website
Klipvia
Explore capabilities
    list_clipsAnswer

    List the clips of the open project with id, name, pixel size, duration, frame rate and background. The selected clip is marked with an asterisk. Filter by a name fragment with query; page with offset (40 per page). Start here to discover clip ids.

    View tool JSON
    {
      "name": "list_clips",
      "kind": "answer",
      "impl": "imperative",
      "description": "List the clips of the open project with id, name, pixel size, duration, frame rate and background. The selected clip is marked with an asterisk. Filter by a name fragment with query; page with offset (40 per page). Start here to discover clip ids.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Only clips whose name contains this, case-insensitive."
          },
          "offset": {
            "type": "integer",
            "description": "Skip this many matches (paging)."
          }
        }
      }
    }
    list_projectsAnswer

    List every saved project with its id and clip count. The open one is marked with an asterisk.

    View tool JSON
    {
      "name": "list_projects",
      "kind": "answer",
      "impl": "imperative",
      "description": "List every saved project with its id and clip count. The open one is marked with an asterisk.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    }
    open_projectAction

    Switch the editor to another project. Clip tools then act on that project.

    View tool JSON
    {
      "name": "open_project",
      "kind": "act",
      "impl": "imperative",
      "description": "Switch the editor to another project. Clip tools then act on that project.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "description": "Project id from list_projects."
          }
        },
        "required": [
          "projectId"
        ]
      }
    }
    create_projectAction

    Create a new project, open it, and select its starter clip. Use this to keep unrelated work apart rather than piling clips into one project.

    View tool JSON
    {
      "name": "create_project",
      "kind": "act",
      "impl": "imperative",
      "description": "Create a new project, open it, and select its starter clip. Use this to keep unrelated work apart rather than piling clips into one project.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Project name."
          }
        },
        "required": [
          "name"
        ]
      }
    }
    select_clipAction

    Make a clip the active one in the editor. Other tools default to the selected clip.

    View tool JSON
    {
      "name": "select_clip",
      "kind": "act",
      "impl": "imperative",
      "description": "Make a clip the active one in the editor. Other tools default to the selected clip.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "clipId": {
            "type": "string",
            "description": "Clip id to select."
          }
        },
        "required": [
          "clipId"
        ]
      }
    }
    get_timelineAnswer

    The open timeline: settings, tracks and every item with id, type, track, start–end in seconds and source in-point. Tracks are listed top to bottom; the last video track is the picture, those above are overlays. Notes left on tracks and items (by a person, or by set_track/set_item) follow a dash — read them, they are instructions. Filter by trackId or a time window when long.

    View tool JSON
    {
      "name": "get_timeline",
      "kind": "answer",
      "impl": "imperative",
      "description": "The open timeline: settings, tracks and every item with id, type, track, start–end in seconds and source in-point. Tracks are listed top to bottom; the last video track is the picture, those above are overlays. Notes left on tracks and items (by a person, or by set_track/set_item) follow a dash — read them, they are instructions. Filter by trackId or a time window when long.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "trackId": {
            "type": "string",
            "description": "Only items on this track."
          },
          "fromSeconds": {
            "type": "number",
            "description": "Only items ending after this time."
          },
          "toSeconds": {
            "type": "number",
            "description": "Only items starting before this time."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    list_timelinesAnswer

    The project as a tree: the main timeline (★, what the project delivers), the sections it plays (⧉, indented, in time order, with where they sit), then timelines placed nowhere yet. Shows claims and notes. The open one is marked *. Pass any id as timelineId to other tools to work there without opening it.

    View tool JSON
    {
      "name": "list_timelines",
      "kind": "answer",
      "impl": "imperative",
      "description": "The project as a tree: the main timeline (★, what the project delivers), the sections it plays (⧉, indented, in time order, with where they sit), then timelines placed nowhere yet. Shows claims and notes. The open one is marked *. Pass any id as timelineId to other tools to work there without opening it.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    }
    get_timeline_stateAnswer

    Playhead position, whether it is playing, timeline length, the selected item, and how many edits can be undone. Cheap; call it before capture_timeline_frame or after a batch of edits.

    View tool JSON
    {
      "name": "get_timeline_state",
      "kind": "answer",
      "impl": "imperative",
      "description": "Playhead position, whether it is playing, timeline length, the selected item, and how many edits can be undone. Cheap; call it before capture_timeline_frame or after a batch of edits.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    }
    list_mediaAnswer

    Video and audio files in the media library, with the filename to use as sourceId, duration, size, frame rate and whether each has picture and sound.

    View tool JSON
    {
      "name": "list_media",
      "kind": "answer",
      "impl": "imperative",
      "description": "Video and audio files in the media library, with the filename to use as sourceId, duration, size, frame rate and whether each has picture and sound.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    }
    list_transcriptsAnswer

    Imported transcripts (SRT, VTT, Whisper JSON) with id, cue count, length, whether they carry word-level timings, and the media file each is bound to.

    View tool JSON
    {
      "name": "list_transcripts",
      "kind": "answer",
      "impl": "imperative",
      "description": "Imported transcripts (SRT, VTT, Whisper JSON) with id, cue count, length, whether they carry word-level timings, and the media file each is bound to.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    }
    get_transcriptAnswer

    Read a transcript window. format "cues" gives timed lines, "words" gives every word with its own start/end (when the source has them), "text" gives plain prose. Times are SOURCE seconds of the media file. Output is capped, so page with fromSeconds; the last line says where to continue.

    View tool JSON
    {
      "name": "get_transcript",
      "kind": "answer",
      "impl": "imperative",
      "description": "Read a transcript window. format \"cues\" gives timed lines, \"words\" gives every word with its own start/end (when the source has them), \"text\" gives plain prose. Times are SOURCE seconds of the media file. Output is capped, so page with fromSeconds; the last line says where to continue.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "transcriptId": {
            "type": "string",
            "description": "From list_transcripts."
          },
          "fromSeconds": {
            "type": "number",
            "description": "Start of the window in source seconds. Default 0."
          },
          "toSeconds": {
            "type": "number",
            "description": "End of the window. Default: as much as fits."
          },
          "format": {
            "type": "string",
            "enum": [
              "cues",
              "words",
              "text"
            ],
            "description": "Default \"cues\"."
          }
        },
        "required": [
          "transcriptId"
        ]
      }
    }
    find_in_transcriptAnswer

    Find where a phrase is spoken. Returns each match with its SOURCE start/end seconds — exact to the word when the transcript has word timings, otherwise the containing cue. Feed the times to cut_source_ranges to remove that speech, or to add_to_timeline (converted through the item's in-point) to place a title where it is said.

    View tool JSON
    {
      "name": "find_in_transcript",
      "kind": "answer",
      "impl": "imperative",
      "description": "Find where a phrase is spoken. Returns each match with its SOURCE start/end seconds — exact to the word when the transcript has word timings, otherwise the containing cue. Feed the times to cut_source_ranges to remove that speech, or to add_to_timeline (converted through the item's in-point) to place a title where it is said.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "transcriptId": {
            "type": "string",
            "description": "From list_transcripts."
          },
          "query": {
            "type": "string",
            "description": "Word or phrase, case-insensitive."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "transcriptId",
          "query"
        ]
      }
    }
    detect_silenceAction

    Find silent gaps from the waveform. With itemId the gaps come back in SEQUENCE seconds for that item; with media (a filename) they come back in SOURCE seconds for the whole file. Tune with thresholdDb / minGapSeconds / keepMs. remove_silence applies the same detection.

    View tool JSON
    {
      "name": "detect_silence",
      "kind": "act",
      "impl": "imperative",
      "description": "Find silent gaps from the waveform. With itemId the gaps come back in SEQUENCE seconds for that item; with media (a filename) they come back in SOURCE seconds for the whole file. Tune with thresholdDb / minGapSeconds / keepMs. remove_silence applies the same detection.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "media": {
            "type": "string",
            "description": "Media filename from list_media, when not using itemId."
          },
          "thresholdDb": {
            "type": "number",
            "description": "Quieter than this is silence. Default -40; raise towards -25 for a noisy room."
          },
          "minGapSeconds": {
            "type": "number",
            "description": "Ignore gaps shorter than this. Default 0.5."
          },
          "keepMs": {
            "type": "integer",
            "description": "Milliseconds of each gap to keep at both ends, so cuts land after the breath. Default 150."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    check_timelineAnswer

    Preflight the timeline for what only shows after rendering: missing media or clips, items running past the end of their file, opaque clips used as overlays (they cover everything beneath), letterboxed footage, captions covering no cues, and a timeline with no sound.

    View tool JSON
    {
      "name": "check_timeline",
      "kind": "answer",
      "impl": "imperative",
      "description": "Preflight the timeline for what only shows after rendering: missing media or clips, items running past the end of their file, opaque clips used as overlays (they cover everything beneath), letterboxed footage, captions covering no cues, and a timeline with no sound.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    capture_timeline_frameAction

    Composite the timeline — footage, overlays and captions stacked exactly as the render will — and show it. With a server you get a PNG URL to fetch; with no server the stage is left parked on that frame for you to look at, and the picture is attached to the result where the runtime supports images. One frame at timeSeconds, or with count 2–12 a labelled contact sheet spread between fromSeconds and toSeconds: the quickest way to see an overlay against the footage over its whole life. The editor is left parked on the last frame.

    View tool JSON
    {
      "name": "capture_timeline_frame",
      "kind": "act",
      "impl": "imperative",
      "description": "Composite the timeline — footage, overlays and captions stacked exactly as the render will — and show it. With a server you get a PNG URL to fetch; with no server the stage is left parked on that frame for you to look at, and the picture is attached to the result where the runtime supports images. One frame at timeSeconds, or with count 2–12 a labelled contact sheet spread between fromSeconds and toSeconds: the quickest way to see an overlay against the footage over its whole life. The editor is left parked on the last frame.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timeSeconds": {
            "type": "number",
            "description": "Timeline time to capture. Defaults to the playhead."
          },
          "count": {
            "type": "integer",
            "description": "Frames for a contact sheet, 2–12."
          },
          "fromSeconds": {
            "type": "number",
            "description": "Sheet start. Default 0."
          },
          "toSeconds": {
            "type": "number",
            "description": "Sheet end. Default the timeline end."
          },
          "timelineId": {
            "type": "string",
            "description": "Open this timeline first (id from list_timelines)."
          }
        }
      }
    }
    create_timelineAction

    Add a timeline to the project and open it. Defaults to 1920x1080, 30fps, black. Comes with tracks V2, V1 (picture) and A1.

    View tool JSON
    {
      "name": "create_timeline",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a timeline to the project and open it. Defaults to 1920x1080, 30fps, black. Comes with tracks V2, V1 (picture) and A1.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Timeline name."
          },
          "width": {
            "type": "integer",
            "description": "Frame width, 16-7680."
          },
          "height": {
            "type": "integer",
            "description": "Frame height, 16-7680."
          },
          "fps": {
            "type": "integer",
            "description": "Frames per second, 1-120."
          },
          "background": {
            "type": "string",
            "description": "\"transparent\" or a #rrggbb colour behind everything."
          }
        }
      }
    }
    open_timelineAction

    Open another timeline of the project in the editor.

    View tool JSON
    {
      "name": "open_timeline",
      "kind": "act",
      "impl": "imperative",
      "description": "Open another timeline of the project in the editor.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timelineId": {
            "type": "string",
            "description": "From list_timelines."
          }
        },
        "required": [
          "timelineId"
        ]
      }
    }
    set_timeline_settingsAction

    Change a timeline's name, frame size, frame rate, background or note, or make it the main timeline. Items are not rescaled; footage refits by its fit mode. A note is read by whoever works there next — leave instructions in it.

    View tool JSON
    {
      "name": "set_timeline_settings",
      "kind": "act",
      "impl": "imperative",
      "description": "Change a timeline's name, frame size, frame rate, background or note, or make it the main timeline. Items are not rescaled; footage refits by its fit mode. A note is read by whoever works there next — leave instructions in it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "New name."
          },
          "width": {
            "type": "integer",
            "description": "Frame width."
          },
          "height": {
            "type": "integer",
            "description": "Frame height."
          },
          "fps": {
            "type": "integer",
            "description": "Frames per second."
          },
          "background": {
            "type": "string",
            "description": "\"transparent\" or #rrggbb."
          },
          "note": {
            "type": "string",
            "description": "Free text about this timeline; \"\" clears it."
          },
          "main": {
            "type": "boolean",
            "description": "true makes this the main timeline — the one the project delivers."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    add_media_from_urlAction

    Bring a video or audio file into the media library. url is a public http(s) URL, or a data: URL (base64; 24 MB decoded at most) when you hold the bytes — a voice-over a tool returned, say. Sniffed on arrival: mp4, m4v, mov, webm, mkv, avi, wav, mp3, m4a, aac, flac, ogg, opus. It is probed and the reply gives the filename to use as sourceId. Anything larger: host it, or ask the person to drop the file in.

    View tool JSON
    {
      "name": "add_media_from_url",
      "kind": "act",
      "impl": "imperative",
      "description": "Bring a video or audio file into the media library. url is a public http(s) URL, or a data: URL (base64; 24 MB decoded at most) when you hold the bytes — a voice-over a tool returned, say. Sniffed on arrival: mp4, m4v, mov, webm, mkv, avi, wav, mp3, m4a, aac, flac, ogg, opus. It is probed and the reply gives the filename to use as sourceId. Anything larger: host it, or ask the person to drop the file in.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Public http(s) URL, or data:<mime>;base64,… holding the file (24 MB decoded max)."
          },
          "name": {
            "type": "string",
            "description": "Optional filename. Its extension is corrected if it disagrees with the bytes."
          }
        },
        "required": [
          "url"
        ]
      }
    }
    list_text_presetsAnswer

    The ready-made animated title styles a text item can use — title, lower third, subtitle bar, pop-words, typewriter, impact, label, quote — with the fields each takes and its default length, plus the shapes add_shape places (rectangle, ellipse, frame, ring, highlight, line, arrow, marker, check, pulse, pointer), each with the add_shape parameters it takes. Use with add_text; no clip code needed.

    View tool JSON
    {
      "name": "list_text_presets",
      "kind": "answer",
      "impl": "imperative",
      "description": "The ready-made animated title styles a text item can use — title, lower third, subtitle bar, pop-words, typewriter, impact, label, quote — with the fields each takes and its default length, plus the shapes add_shape places (rectangle, ellipse, frame, ring, highlight, line, arrow, marker, check, pulse, pointer), each with the add_shape parameters it takes. Use with add_text; no clip code needed.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    }
    add_textAction

    Put an animated title on the timeline from a preset: type the words, pick the preset, place it. (For a shape — a rectangle, frame, ring, arrow, marker and so on — use add_shape.) It animates in from its start and out at its end, whatever length it is given. Placement uses anchor; style takes fontFamily, fontSize, color, accent, boxColor, weight, uppercase, align. Convertible to a clip later for full control.

    View tool JSON
    {
      "name": "add_text",
      "kind": "act",
      "impl": "imperative",
      "description": "Put an animated title on the timeline from a preset: type the words, pick the preset, place it. (For a shape — a rectangle, frame, ring, arrow, marker and so on — use add_shape.) It animates in from its start and out at its end, whatever length it is given. Placement uses anchor; style takes fontFamily, fontSize, color, accent, boxColor, weight, uppercase, align. Convertible to a clip later for full control.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "preset": {
            "type": "string",
            "description": "Preset id from list_text_presets. Default \"title\"."
          },
          "text": {
            "type": "string",
            "description": "The words."
          },
          "subtext": {
            "type": "string",
            "description": "Second line, for presets that have one (lower-third role, quote attribution, title strap)."
          },
          "atSeconds": {
            "type": "number",
            "description": "Start on the timeline. Defaults to the playhead."
          },
          "durationSeconds": {
            "type": "number",
            "description": "Length. Defaults to the preset default."
          },
          "trackId": {
            "type": "string",
            "description": "A video track id; otherwise a free overlay track is chosen or made."
          },
          "anchor": {
            "type": "string",
            "enum": [
              "center",
              "top",
              "bottom",
              "left",
              "right",
              "top-left",
              "top-right",
              "bottom-left",
              "bottom-right"
            ],
            "description": "Nudge the whole title from the preset's own placement."
          },
          "style": {
            "type": "object",
            "description": "fontFamily, fontSize, color, accent, boxColor, weight, uppercase, align."
          },
          "name": {
            "type": "string",
            "description": "Item name on the timeline; defaults to the text."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "text"
        ]
      }
    }
    add_shapeAction

    Put a shape on the timeline, sized in timeline pixels and placed by anchor and offsets (default anchor top-left, so offsetX/offsetY are its top-left corner in frame pixels; anchor center places its middle). rect and ellipse are solid patches that cut in and out: in the footage's own colour (save_frame or capture_timeline_frame to read it) a rect hides an account name or a detail. frame and ring are outlines that draw themselves on around something (fill none by default). highlight is a translucent wash swiped over a line or a button. line and arrow draw from one end to the other: points is the end they draw towards, where the arrow's head is (for up or down make height the long side). marker is a numbered dot for steps (label is the number, "1" by default). check is a tick in a disc: the disc pops, then the tick draws. pulse is a dot with rings rippling outward, for "click here". pointer is a mouse pointer that lands and clicks once; its tip is the item's centre, so anchor center plus offsets place the tip. Lines are white with a small shadow by default; dashed makes a frame, ring, line or arrow dashed (it then fades in rather than drawing on). It is a text item with no words, so set_item changes it later (textStyle width/height/radius/stroke/color/accent/direction/dashed, text for a marker's number, offsetX/offsetY, opacity, timing) and it renders like any overlay.

    View tool JSON
    {
      "name": "add_shape",
      "kind": "act",
      "impl": "imperative",
      "description": "Put a shape on the timeline, sized in timeline pixels and placed by anchor and offsets (default anchor top-left, so offsetX/offsetY are its top-left corner in frame pixels; anchor center places its middle). rect and ellipse are solid patches that cut in and out: in the footage's own colour (save_frame or capture_timeline_frame to read it) a rect hides an account name or a detail. frame and ring are outlines that draw themselves on around something (fill none by default). highlight is a translucent wash swiped over a line or a button. line and arrow draw from one end to the other: points is the end they draw towards, where the arrow's head is (for up or down make height the long side). marker is a numbered dot for steps (label is the number, \"1\" by default). check is a tick in a disc: the disc pops, then the tick draws. pulse is a dot with rings rippling outward, for \"click here\". pointer is a mouse pointer that lands and clicks once; its tip is the item's centre, so anchor center plus offsets place the tip. Lines are white with a small shadow by default; dashed makes a frame, ring, line or arrow dashed (it then fades in rather than drawing on). It is a text item with no words, so set_item changes it later (textStyle width/height/radius/stroke/color/accent/direction/dashed, text for a marker's number, offsetX/offsetY, opacity, timing) and it renders like any overlay.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "shape": {
            "type": "string",
            "enum": [
              "rect",
              "ellipse",
              "frame",
              "ring",
              "highlight",
              "line",
              "arrow",
              "marker",
              "check",
              "pulse",
              "pointer"
            ],
            "description": "Default rect."
          },
          "width": {
            "type": "number",
            "description": "Pixels at timeline size. Rounded to even."
          },
          "height": {
            "type": "number",
            "description": "Pixels at timeline size. Rounded to even."
          },
          "fill": {
            "type": "string",
            "description": "#rrggbb, or \"none\": the patch, the marker or check disc, the pulse's dot, the pointer's body. Frames and rings default to none; a highlight is drawn translucent whatever the colour."
          },
          "outline": {
            "type": "string",
            "description": "Line colour #rrggbb: a patch's outline, the stroke of a frame, ring, line or arrow, the marker's number, the check's tick, the pulse's rings, the pointer's edge. Default white (the pointer's is near-black)."
          },
          "outlineWidth": {
            "type": "number",
            "description": "Line weight in pixels. 0 = no outline on a patch, marker or check; frames, rings, lines and arrows default to 6; pulse rings and the pointer's edge to 4."
          },
          "corners": {
            "type": "number",
            "description": "Corner radius in pixels for a rect, frame, highlight, marker or check. 999 is a circle (the marker and check default)."
          },
          "points": {
            "type": "string",
            "enum": [
              "right",
              "left",
              "up",
              "down"
            ],
            "description": "Line and arrow: the end it draws towards, where the head is. Default right."
          },
          "dashed": {
            "type": "boolean",
            "description": "Frame, ring, line, arrow: draw the stroke dashed. A dashed stroke fades in rather than drawing on."
          },
          "label": {
            "type": "string",
            "description": "Marker: the number or short label in the dot. Default \"1\"."
          },
          "opacity": {
            "type": "number",
            "description": "Whole-item opacity 0–1. Default 1."
          },
          "anchor": {
            "type": "string",
            "enum": [
              "center",
              "top",
              "bottom",
              "left",
              "right",
              "top-left",
              "top-right",
              "bottom-left",
              "bottom-right"
            ],
            "description": "Where the offsets are measured from. Default top-left."
          },
          "offsetX": {
            "type": "number",
            "description": "Pixels from the anchor, rightwards."
          },
          "offsetY": {
            "type": "number",
            "description": "Pixels from the anchor, downwards."
          },
          "atSeconds": {
            "type": "number",
            "description": "Start on the timeline. Defaults to the playhead."
          },
          "durationSeconds": {
            "type": "number",
            "description": "Length. Default 5."
          },
          "trackId": {
            "type": "string",
            "description": "A video track id; otherwise a free overlay track is chosen or made."
          },
          "name": {
            "type": "string",
            "description": "Item name on the timeline; defaults to the shape name."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    add_to_timelineAction

    Place a source on the timeline. kind "media" takes a filename from list_media, "clip" a clip id (an overlay layer with real alpha), "transcript" an id (burnt-in captions, auto-aligned to its footage if placed), "timeline" another timeline id (a block that plays it — a section). Without trackId a free track is chosen or made; nothing is overwritten. Returns the new item id.

    View tool JSON
    {
      "name": "add_to_timeline",
      "kind": "act",
      "impl": "imperative",
      "description": "Place a source on the timeline. kind \"media\" takes a filename from list_media, \"clip\" a clip id (an overlay layer with real alpha), \"transcript\" an id (burnt-in captions, auto-aligned to its footage if placed), \"timeline\" another timeline id (a block that plays it — a section). Without trackId a free track is chosen or made; nothing is overwritten. Returns the new item id.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "media",
              "clip",
              "transcript",
              "timeline",
              "image"
            ],
            "description": "What sourceId refers to. image = an image asset filename from list_assets: a still on an overlay track, held for durationSeconds (default 5), sized in set_item via imageStyle {width, height, radius, shadow} and fit."
          },
          "sourceId": {
            "type": "string",
            "description": "Media filename, clip id, transcript id, timeline id or image asset filename."
          },
          "atSeconds": {
            "type": "number",
            "description": "Where it starts on the timeline. Defaults to the playhead."
          },
          "durationSeconds": {
            "type": "number",
            "description": "Length on the timeline. Defaults to the source length."
          },
          "inSeconds": {
            "type": "number",
            "description": "In-point inside the source. Default 0."
          },
          "trackId": {
            "type": "string",
            "description": "A track id from get_timeline. Placing over an existing item trims it out of the way."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "kind",
          "sourceId"
        ]
      }
    }
    set_itemAction

    Change one item: timing (start, length, in-point), placement (fit for footage; anchor/offsetX/offsetY for overlays), size (scale for footage, nested blocks and animation clips; imageStyle/textStyle width and height for images and shapes; textStyle fontSize for titles), transform (rotation, flipH, flipV, crop), look (colour, blend, radius, shadow), opacity, sound (volume, muted, fades), captionStyle for captions, text/subtext/preset/textStyle for titles, or a note. Only the fields given change. A longer item trims whatever it now overlaps.

    View tool JSON
    {
      "name": "set_item",
      "kind": "act",
      "impl": "imperative",
      "description": "Change one item: timing (start, length, in-point), placement (fit for footage; anchor/offsetX/offsetY for overlays), size (scale for footage, nested blocks and animation clips; imageStyle/textStyle width and height for images and shapes; textStyle fontSize for titles), transform (rotation, flipH, flipV, crop), look (colour, blend, radius, shadow), opacity, sound (volume, muted, fades), captionStyle for captions, text/subtext/preset/textStyle for titles, or a note. Only the fields given change. A longer item trims whatever it now overlaps.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          },
          "startSeconds": {
            "type": "number",
            "description": "Start on the timeline."
          },
          "durationSeconds": {
            "type": "number",
            "description": "Length on the timeline."
          },
          "inSeconds": {
            "type": "number",
            "description": "In-point inside the source."
          },
          "fit": {
            "type": "string",
            "enum": [
              "contain",
              "cover",
              "fill",
              "none"
            ],
            "description": "Footage: letterbox, crop, stretch, or native size."
          },
          "anchor": {
            "type": "string",
            "enum": [
              "center",
              "top",
              "bottom",
              "left",
              "right",
              "top-left",
              "top-right",
              "bottom-left",
              "bottom-right"
            ],
            "description": "Where an overlay (or fit:none footage) sits."
          },
          "offsetX": {
            "type": "integer",
            "description": "Pixels from the anchor, horizontally."
          },
          "offsetY": {
            "type": "integer",
            "description": "Pixels from the anchor, vertically."
          },
          "speed": {
            "type": "number",
            "description": "Footage, nested blocks and animation clips only: how fast the source runs against the timeline. 1 is normal, 2 plays twice as fast, 0.5 is slow motion. The item keeps its length on the timeline and shows more or less of the source; sound is re-timed with its pitch kept. A caption or a title has no speed — its timing comes from its transcript or its own length."
          },
          "dissolveInSeconds": {
            "type": "number",
            "description": "Fade the picture up over this long at the start. Half of a cross dissolve."
          },
          "dissolveOutSeconds": {
            "type": "number",
            "description": "Fade the picture down over this long at the end."
          },
          "scale": {
            "type": "number",
            "description": "Footage, nested blocks and animation clips only, and only with fit:none: how big the layer is drawn against its natural size. 1 is unchanged, 0.3 is a picture-in-picture corner. An animation clip is re-rendered at that size, so it stays sharp; footage is resampled. An image, shape or title has no scale — give it a size instead."
          },
          "rotation": {
            "type": "number",
            "description": "Degrees clockwise, about the middle of the layer. -180 to 180."
          },
          "flipH": {
            "type": "boolean",
            "description": "Mirror left to right."
          },
          "flipV": {
            "type": "boolean",
            "description": "Mirror top to bottom."
          },
          "crop": {
            "type": "object",
            "description": "Footage and nested blocks only: how much of each edge to cut off before the fit, as fractions 0-0.95 — {top, right, bottom, left}. Fractions of the source, so the framing survives swapping the shot for another resolution. null clears it."
          },
          "colour": {
            "type": "object",
            "description": "Colour correction: {brightness, contrast, saturation} where 1 is unchanged, and {temperature} from -1 (cool) to 1 (warm). null clears it."
          },
          "blend": {
            "type": "string",
            "enum": [
              "normal",
              "multiply",
              "screen",
              "overlay",
              "darken",
              "lighten",
              "softlight",
              "hardlight",
              "difference",
              "exclusion"
            ],
            "description": "How the layer mixes with what is under it."
          },
          "radius": {
            "type": "integer",
            "description": "Round the layer's corners, in frame pixels. 0 is square."
          },
          "shadow": {
            "type": "object",
            "description": "A drop shadow under the layer: {blur, x, y, color, opacity}. blur 0 turns it off; null clears it. This is what makes a picture-in-picture read as a card over the footage."
          },
          "opacity": {
            "type": "number",
            "description": "0-1."
          },
          "volume": {
            "type": "number",
            "description": "0-4; 1 is unchanged."
          },
          "muted": {
            "type": "boolean",
            "description": "Silence the item."
          },
          "fadeInSeconds": {
            "type": "number",
            "description": "Audio fade in."
          },
          "fadeOutSeconds": {
            "type": "number",
            "description": "Audio fade out."
          },
          "captionStyle": {
            "type": "object",
            "description": "Caption items: fontSize, color, boxColor, position (top|center|bottom), marginPx, maxWidthPct, uppercase, shadow, fontFamily, weight, transition (cut|fade|pop), karaoke (off|word|fill), accent."
          },
          "note": {
            "type": "string",
            "description": "Free text kept on the item and shown in get_timeline. Empty string clears it."
          },
          "text": {
            "type": "string",
            "description": "Text items: the words."
          },
          "subtext": {
            "type": "string",
            "description": "Text items: the second line, where the preset has one."
          },
          "preset": {
            "type": "string",
            "description": "Text items: switch preset (see list_text_presets)."
          },
          "imageStyle": {
            "type": "object",
            "description": "Image items: width, height (pixels at timeline size; omit for natural size), radius (corner px), shadow (boolean). Use fit for contain/cover/fill/none."
          },
          "textStyle": {
            "type": "object",
            "description": "Text items: fontFamily, fontSize, color, accent, boxColor, weight (400-900), uppercase, align (left|center|right). Shapes: width, height, radius, stroke (the one line weight), color (fill), accent (line), direction (right|left|up|down), dashed; a marker's number is the item's text."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    move_itemAction

    Move an item to a time, optionally onto another track of the same kind. Whatever it lands on is trimmed out of its way.

    View tool JSON
    {
      "name": "move_item",
      "kind": "act",
      "impl": "imperative",
      "description": "Move an item to a time, optionally onto another track of the same kind. Whatever it lands on is trimmed out of its way.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "atSeconds": {
            "type": "number",
            "description": "New start time."
          },
          "trackId": {
            "type": "string",
            "description": "Destination track id."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId",
          "atSeconds"
        ]
      }
    }
    split_itemAction

    Cut an item in two at a timeline time (default: the playhead). The tail keeps source continuity, so the cut does not jump. Returns both ids.

    View tool JSON
    {
      "name": "split_item",
      "kind": "act",
      "impl": "imperative",
      "description": "Cut an item in two at a timeline time (default: the playhead). The tail keeps source continuity, so the cut does not jump. Returns both ids.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "atSeconds": {
            "type": "number",
            "description": "Timeline time inside the item."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    delete_itemSensitive Action

    Remove an item. ripple:true also closes the gap by pulling everything after it on that track back.

    View tool JSON
    {
      "name": "delete_item",
      "kind": "transact",
      "impl": "imperative",
      "description": "Remove an item. ripple:true also closes the gap by pulling everything after it on that track back.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "ripple": {
            "type": "boolean",
            "description": "Close the gap on that track. Default false."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    cut_time_rangeAction

    Remove a stretch of SEQUENCE time from every unlocked track and close the gap — items spanning it are cut and rejoined, later items slide back. Lock a track (set_track) to protect a music bed. Undoable.

    View tool JSON
    {
      "name": "cut_time_range",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove a stretch of SEQUENCE time from every unlocked track and close the gap — items spanning it are cut and rejoined, later items slide back. Lock a track (set_track) to protect a music bed. Undoable.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "fromSeconds": {
            "type": "number",
            "description": "Start of the range."
          },
          "toSeconds": {
            "type": "number",
            "description": "End of the range."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "fromSeconds",
          "toSeconds"
        ]
      }
    }
    cut_source_rangesAction

    Remove parts of an item by SOURCE time — the times find_in_transcript and get_transcript give — and ripple the whole timeline closed. This is how "cut the part where she repeats herself" or "drop every um" is done: find the words, pass their ranges. Captions on the same footage stay in sync. Undoable.

    View tool JSON
    {
      "name": "cut_source_ranges",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove parts of an item by SOURCE time — the times find_in_transcript and get_transcript give — and ripple the whole timeline closed. This is how \"cut the part where she repeats herself\" or \"drop every um\" is done: find the words, pass their ranges. Captions on the same footage stay in sync. Undoable.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "ranges": {
            "type": "array",
            "description": "Source-time ranges to remove, e.g. [{\"fromSeconds\":12.3,\"toSeconds\":12.9}].",
            "items": {
              "type": "object",
              "properties": {
                "fromSeconds": {
                  "type": "number"
                },
                "toSeconds": {
                  "type": "number"
                }
              },
              "required": [
                "fromSeconds",
                "toSeconds"
              ]
            }
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId",
          "ranges"
        ]
      }
    }
    remove_silenceAction

    Detect the silent gaps in an item and cut them all out of the timeline, rippling every unlocked track so captions and overlays stay aligned. Run detect_silence first to see what will go; lock a music bed with set_track. Undoable.

    View tool JSON
    {
      "name": "remove_silence",
      "kind": "act",
      "impl": "imperative",
      "description": "Detect the silent gaps in an item and cut them all out of the timeline, rippling every unlocked track so captions and overlays stay aligned. Run detect_silence first to see what will go; lock a music bed with set_track. Undoable.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "thresholdDb": {
            "type": "number",
            "description": "Quieter than this is silence. Default -40; raise towards -25 for a noisy room."
          },
          "minGapSeconds": {
            "type": "number",
            "description": "Ignore gaps shorter than this. Default 0.5."
          },
          "keepMs": {
            "type": "integer",
            "description": "Milliseconds of each gap to keep at both ends, so cuts land after the breath. Default 150."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    replace_audioAction

    Put a different sound under an item — the new voice back from a voice tool, say. The item's own sound is muted and the new file is laid on an audio track aligned to the item's start. The reply says if the new sound is shorter or longer than the picture, so you can trim or hold it. Then edit_transcript to update the words.

    View tool JSON
    {
      "name": "replace_audio",
      "kind": "act",
      "impl": "imperative",
      "description": "Put a different sound under an item — the new voice back from a voice tool, say. The item's own sound is muted and the new file is laid on an audio track aligned to the item's start. The reply says if the new sound is shorter or longer than the picture, so you can trim or hold it. Then edit_transcript to update the words.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "media": {
            "type": "string",
            "description": "The new sound: a media filename from list_media (import it first with add_media_from_url or a drop)."
          },
          "inSeconds": {
            "type": "number",
            "description": "In-point inside the new sound. Default 0."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId",
          "media"
        ]
      }
    }
    edit_transcriptAction

    Replace what is said in a window of SOURCE time: cues wholly inside go, cues crossing an edge are cut at it, the new cues are put in. This is how the words of a re-voiced part are updated — captions on that footage recompile. Edited cues have no word timings (karaoke falls back to plain). Not part of undo_edit; undo_transcript_edit reverts it.

    View tool JSON
    {
      "name": "edit_transcript",
      "kind": "act",
      "impl": "imperative",
      "description": "Replace what is said in a window of SOURCE time: cues wholly inside go, cues crossing an edge are cut at it, the new cues are put in. This is how the words of a re-voiced part are updated — captions on that footage recompile. Edited cues have no word timings (karaoke falls back to plain). Not part of undo_edit; undo_transcript_edit reverts it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "transcriptId": {
            "type": "string",
            "description": "From list_transcripts."
          },
          "fromSeconds": {
            "type": "number",
            "description": "Start of the window, source time."
          },
          "toSeconds": {
            "type": "number",
            "description": "End of the window, source time."
          },
          "cues": {
            "type": "array",
            "description": "The new lines, e.g. [{\"fromSeconds\":12.3,\"toSeconds\":15,\"text\":\"…\"}]. Empty array just clears the window.",
            "items": {
              "type": "object",
              "properties": {
                "fromSeconds": {
                  "type": "number"
                },
                "toSeconds": {
                  "type": "number"
                },
                "text": {
                  "type": "string"
                }
              },
              "required": [
                "fromSeconds",
                "toSeconds",
                "text"
              ]
            }
          }
        },
        "required": [
          "transcriptId",
          "fromSeconds",
          "toSeconds",
          "cues"
        ]
      }
    }
    set_cueAction

    Change one cue by index (from get_transcript order): its text, start or end in source seconds, or delete it. Text edits drop that cue's word timings. Reverted by undo_transcript_edit.

    View tool JSON
    {
      "name": "set_cue",
      "kind": "act",
      "impl": "imperative",
      "description": "Change one cue by index (from get_transcript order): its text, start or end in source seconds, or delete it. Text edits drop that cue's word timings. Reverted by undo_transcript_edit.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "transcriptId": {
            "type": "string",
            "description": "From list_transcripts."
          },
          "index": {
            "type": "integer",
            "description": "Zero-based cue index."
          },
          "text": {
            "type": "string",
            "description": "New words."
          },
          "fromSeconds": {
            "type": "number",
            "description": "New start."
          },
          "toSeconds": {
            "type": "number",
            "description": "New end."
          },
          "delete": {
            "type": "boolean",
            "description": "Remove the cue instead."
          }
        },
        "required": [
          "transcriptId",
          "index"
        ]
      }
    }
    undo_transcript_editAction

    Revert the last edit_transcript / set_cue on a transcript (twenty deep, this session).

    View tool JSON
    {
      "name": "undo_transcript_edit",
      "kind": "act",
      "impl": "imperative",
      "description": "Revert the last edit_transcript / set_cue on a transcript (twenty deep, this session).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "transcriptId": {
            "type": "string",
            "description": "From list_transcripts."
          }
        },
        "required": [
          "transcriptId"
        ]
      }
    }
    get_narrationAnswer

    What is said when, in TIMELINE seconds — the map to plan overlays from ("put the keycap where he presses Ctrl"). Uses the captions placed on the timeline, else the transcript bound to its footage, mapped through each item's in-point. Filter with a time window or a query phrase.

    View tool JSON
    {
      "name": "get_narration",
      "kind": "answer",
      "impl": "imperative",
      "description": "What is said when, in TIMELINE seconds — the map to plan overlays from (\"put the keycap where he presses Ctrl\"). Uses the captions placed on the timeline, else the transcript bound to its footage, mapped through each item's in-point. Filter with a time window or a query phrase.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "fromSeconds": {
            "type": "number",
            "description": "Only lines after this timeline time."
          },
          "toSeconds": {
            "type": "number",
            "description": "Only lines before this timeline time."
          },
          "query": {
            "type": "string",
            "description": "Only lines containing this phrase, case-insensitive."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    check_layoutAnswer

    Where the overlays sit on screen, and which collide. Each overlay is drawn offscreen and the box of what it actually paints measured (at a quarter, half and three quarters of its life); pairs that share time and pixels — a title over the captions, two cards in the same corner — are reported with the overlap. Run it after placing overlays; a window keeps it quick.

    View tool JSON
    {
      "name": "check_layout",
      "kind": "answer",
      "impl": "imperative",
      "description": "Where the overlays sit on screen, and which collide. Each overlay is drawn offscreen and the box of what it actually paints measured (at a quarter, half and three quarters of its life); pairs that share time and pixels — a title over the captions, two cards in the same corner — are reported with the overlap. Run it after placing overlays; a window keeps it quick.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "fromSeconds": {
            "type": "number",
            "description": "Window start."
          },
          "toSeconds": {
            "type": "number",
            "description": "Window end."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    duplicate_timelineAction

    Copy a timeline as a new version — every track and item with fresh ids, placed right after the original, named "<name> v2" unless told otherwise. Sections (blocks playing other timelines) stay shared; deep: true copies them too, recursively, so the version can diverge all the way down. Opens the copy unless open: false. Iterate on the copy; the original is untouched.

    View tool JSON
    {
      "name": "duplicate_timeline",
      "kind": "act",
      "impl": "imperative",
      "description": "Copy a timeline as a new version — every track and item with fresh ids, placed right after the original, named \"<name> v2\" unless told otherwise. Sections (blocks playing other timelines) stay shared; deep: true copies them too, recursively, so the version can diverge all the way down. Opens the copy unless open: false. Iterate on the copy; the original is untouched.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name for the copy. Default: the original's name with the next version number."
          },
          "deep": {
            "type": "boolean",
            "description": "Also copy the timelines its blocks play (default false: shared)."
          },
          "open": {
            "type": "boolean",
            "description": "Open the copy (default true)."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    delete_timelineSensitive Action

    Remove a timeline document — a version you are done with. Refused for the main timeline and for one placed as a section somewhere (flatten or delete the blocks first). Its undo history goes with it; the timeline is not recoverable.

    View tool JSON
    {
      "name": "delete_timeline",
      "kind": "transact",
      "impl": "imperative",
      "description": "Remove a timeline document — a version you are done with. Refused for the main timeline and for one placed as a section somewhere (flatten or delete the blocks first). Its undo history goes with it; the timeline is not recoverable.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timelineId": {
            "type": "string",
            "description": "The timeline to delete, from list_timelines. Required — never the open one by default."
          }
        },
        "required": [
          "timelineId"
        ]
      }
    }
    claim_timelineAction

    Say who is working on a timeline, so others keep off. Advisory: the claim shows in list_timelines and the rail; once you have named yourself here, edits to a timeline another agent holds are refused unless you take it over with force. Claims lapse after fifteen minutes; claim again to renew, release when done.

    View tool JSON
    {
      "name": "claim_timeline",
      "kind": "act",
      "impl": "imperative",
      "description": "Say who is working on a timeline, so others keep off. Advisory: the claim shows in list_timelines and the rail; once you have named yourself here, edits to a timeline another agent holds are refused unless you take it over with force. Claims lapse after fifteen minutes; claim again to renew, release when done.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timelineId": {
            "type": "string",
            "description": "Id from list_timelines. Defaults to the open timeline."
          },
          "agent": {
            "type": "string",
            "description": "Your name for this session, e.g. \"agent-intro\". Remembered for later calls."
          },
          "release": {
            "type": "boolean",
            "description": "true gives the claim up."
          },
          "force": {
            "type": "boolean",
            "description": "true takes over another agent's claim."
          }
        },
        "required": [
          "agent"
        ]
      }
    }
    nest_itemsAction

    Group items into a new sub-timeline: they move into it (same layout, re-based to zero) and one block plays it in their place. The block opens as its own timeline — the unit of work to hand to an agent. Nothing is overwritten; a member on a locked track refuses the whole group. Returns the new timeline id and the block id.

    View tool JSON
    {
      "name": "nest_items",
      "kind": "act",
      "impl": "imperative",
      "description": "Group items into a new sub-timeline: they move into it (same layout, re-based to zero) and one block plays it in their place. The block opens as its own timeline — the unit of work to hand to an agent. Nothing is overwritten; a member on a locked track refuses the whole group. Returns the new timeline id and the block id.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Item ids from get_timeline. Defaults to the selection."
          },
          "name": {
            "type": "string",
            "description": "Name of the new sub-timeline."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    flatten_itemAction

    Replace a timeline block with the items inside it, on parent tracks of the same kind and name (new tracks where those are busy; nothing is overwritten). Items are clipped to the block's window, volume and opacity scaled by the block's; the block's own fades are dropped. The sub-timeline itself stays in the project.

    View tool JSON
    {
      "name": "flatten_item",
      "kind": "act",
      "impl": "imperative",
      "description": "Replace a timeline block with the items inside it, on parent tracks of the same kind and name (new tracks where those are busy; nothing is overwritten). Items are clipped to the block's window, volume and opacity scaled by the block's; the block's own fades are dropped. The sub-timeline itself stays in the project.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "The block's item id from get_timeline."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    select_itemsAction

    Select items on the timeline, as shift-clicking them would. The selection is what the Export parts dialog and the multi-item actions start from; an empty list clears it.

    View tool JSON
    {
      "name": "select_items",
      "kind": "act",
      "impl": "imperative",
      "description": "Select items on the timeline, as shift-clicking them would. The selection is what the Export parts dialog and the multi-item actions start from; an empty list clears it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Item ids from get_timeline."
          },
          "timelineId": {
            "type": "string",
            "description": "Open this timeline first (id from list_timelines)."
          }
        },
        "required": [
          "itemIds"
        ]
      }
    }
    detach_audioAction

    Separate an item's sound from its picture: the sound becomes its own item on an audio track (same file, in-point and length) and the picture is muted. Then either can be trimmed, moved, replaced (replace_audio) or silenced on its own. One undo step.

    View tool JSON
    {
      "name": "detach_audio",
      "kind": "act",
      "impl": "imperative",
      "description": "Separate an item's sound from its picture: the sound becomes its own item on an audio track (same file, in-point and length) and the picture is muted. Then either can be trimmed, moved, replaced (replace_audio) or silenced on its own. One undo step.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    add_trackAction

    Add a video track (above the others) or an audio track (below).

    View tool JSON
    {
      "name": "add_track",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a video track (above the others) or an audio track (below).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "video",
              "audio"
            ],
            "description": "Track kind."
          },
          "name": {
            "type": "string",
            "description": "Optional name, e.g. \"Titles\"."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "kind"
        ]
      }
    }
    export_captionsAction

    One subtitle file from the timeline's caption items — every caption item when itemIds is empty, or just those — timed as the captions fall on the timeline, so it lines up with the rendered video (times "source" keeps the original file's times; one transcript only). SRT, WebVTT or plain text (the words alone). Written into Exports; fetch the returned URL.

    View tool JSON
    {
      "name": "export_captions",
      "kind": "act",
      "impl": "imperative",
      "description": "One subtitle file from the timeline's caption items — every caption item when itemIds is empty, or just those — timed as the captions fall on the timeline, so it lines up with the rendered video (times \"source\" keeps the original file's times; one transcript only). SRT, WebVTT or plain text (the words alone). Written into Exports; fetch the returned URL.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caption item ids from get_timeline. Omit for all of them."
          },
          "format": {
            "type": "string",
            "enum": [
              "srt",
              "vtt",
              "txt"
            ],
            "description": "Default srt."
          },
          "times": {
            "type": "string",
            "enum": [
              "timeline",
              "source"
            ],
            "description": "Default timeline."
          },
          "name": {
            "type": "string",
            "description": "File name without extension. Defaults to the item or timeline name."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    move_trackAction

    Reorder a track among those of its kind. Order is stacking order: the top track draws over everything beneath it, in the preview and in the render, so an overlay track that must show over another goes above it. Video tracks always stay above audio tracks. Give a direction (up, down, top, bottom) or a position counted from the top within the kind (0 = topmost). get_timeline lists tracks top to bottom.

    View tool JSON
    {
      "name": "move_track",
      "kind": "act",
      "impl": "imperative",
      "description": "Reorder a track among those of its kind. Order is stacking order: the top track draws over everything beneath it, in the preview and in the render, so an overlay track that must show over another goes above it. Video tracks always stay above audio tracks. Give a direction (up, down, top, bottom) or a position counted from the top within the kind (0 = topmost). get_timeline lists tracks top to bottom.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "trackId": {
            "type": "string",
            "description": "Track id or name from get_timeline."
          },
          "direction": {
            "type": "string",
            "enum": [
              "up",
              "down",
              "top",
              "bottom"
            ],
            "description": "One step, or all the way."
          },
          "index": {
            "type": "integer",
            "description": "Position from the top among tracks of the same kind, 0 = topmost. Overrides direction."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "trackId"
        ]
      }
    }
    set_trackAction

    Rename, colour, annotate, mute, hide or lock a track. A note is free text shown in get_timeline — leave instructions for later. A locked track is skipped by cut_time_range, cut_source_ranges and remove_silence.

    View tool JSON
    {
      "name": "set_track",
      "kind": "act",
      "impl": "imperative",
      "description": "Rename, colour, annotate, mute, hide or lock a track. A note is free text shown in get_timeline — leave instructions for later. A locked track is skipped by cut_time_range, cut_source_ranges and remove_silence.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "trackId": {
            "type": "string",
            "description": "From get_timeline."
          },
          "name": {
            "type": "string",
            "description": "New name, e.g. \"Lower thirds\"."
          },
          "note": {
            "type": "string",
            "description": "Free text kept on the track. Empty string clears it."
          },
          "color": {
            "type": "string",
            "description": "#rrggbb swatch for the track, or \"none\"."
          },
          "muted": {
            "type": "boolean",
            "description": "Silence the whole track."
          },
          "hidden": {
            "type": "boolean",
            "description": "Hide a video track from preview and render."
          },
          "locked": {
            "type": "boolean",
            "description": "Protect it from ripple edits."
          },
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        },
        "required": [
          "trackId"
        ]
      }
    }
    seek_timelineAction

    Move the timeline playhead so the preview shows that moment.

    View tool JSON
    {
      "name": "seek_timeline",
      "kind": "act",
      "impl": "imperative",
      "description": "Move the timeline playhead so the preview shows that moment.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timeSeconds": {
            "type": "number",
            "description": "Timeline time."
          },
          "timelineId": {
            "type": "string",
            "description": "Open this timeline first (id from list_timelines)."
          }
        },
        "required": [
          "timeSeconds"
        ]
      }
    }
    speech_setupAction

    What this browser can currently do with speech: whether transcription and a voice are set up, which provider each uses, and where the audio would go. Call it before promising to transcribe or narrate — none of it is configured by default, and only the person at the keyboard can add a key. In the UI this is the Speech tab in the left rail: its foot names the provider for each job, and its Providers… button is where one is set up when nothing is.

    View tool JSON
    {
      "name": "speech_setup",
      "kind": "act",
      "impl": "imperative",
      "description": "What this browser can currently do with speech: whether transcription and a voice are set up, which provider each uses, and where the audio would go. Call it before promising to transcribe or narrate — none of it is configured by default, and only the person at the keyboard can add a key. In the UI this is the Speech tab in the left rail: its foot names the provider for each job, and its Providers… button is where one is set up when nothing is.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      }
    }
    transcribe_mediaAction

    Write down what is said in a library file, using whatever transcription the person has set up, and add the words as a transcript. Comes back with word timings where the provider gives them, so the result can be placed as karaoke captions. Check speech_setup first. The same job as the Transcribe button in the Speech rail, on a media tile with sound, and in a selected item’s Sound section.

    View tool JSON
    {
      "name": "transcribe_media",
      "kind": "act",
      "impl": "imperative",
      "description": "Write down what is said in a library file, using whatever transcription the person has set up, and add the words as a transcript. Comes back with word timings where the provider gives them, so the result can be placed as karaoke captions. Check speech_setup first. The same job as the Transcribe button in the Speech rail, on a media tile with sound, and in a selected item’s Sound section.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "description": "The filename from list_media."
          }
        },
        "required": [
          "sourceId"
        ]
      }
    }
    add_voice_overAction

    Read a script aloud into an audio file and drop it on an audio track. Needs a voice that returns audio — the computer’s own voices cannot be recorded. Check speech_setup first; use time_script to see how long a script runs before committing to it. The same job as the Write a voice-over… button in the Speech rail, Voice-over… in a selected item’s Sound section, and Voice-over from these lines… on a caption item.

    View tool JSON
    {
      "name": "add_voice_over",
      "kind": "act",
      "impl": "imperative",
      "description": "Read a script aloud into an audio file and drop it on an audio track. Needs a voice that returns audio — the computer’s own voices cannot be recorded. Check speech_setup first; use time_script to see how long a script runs before committing to it. The same job as the Write a voice-over… button in the Speech rail, Voice-over… in a selected item’s Sound section, and Voice-over from these lines… on a caption item.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "What should be said."
          },
          "voice": {
            "type": "string",
            "description": "Voice id from list_voices. Default: the one chosen in the panel."
          },
          "language": {
            "type": "string",
            "description": "ISO code the script is in (es, en, pt…). Picks a voice of that language where each voice speaks one, or is sent with the script where voices are multilingual. Default: the language chosen in the panel, else auto."
          },
          "name": {
            "type": "string",
            "description": "A name for the audio file."
          },
          "atSeconds": {
            "type": "number",
            "description": "Where on the timeline it starts. Defaults to the playhead."
          }
        },
        "required": [
          "text"
        ]
      }
    }
    list_voicesAnswer

    The voices the chosen voice provider can speak with, grouped by language, each with the id to pass as voice to add_voice_over — and which voice and language the person has selected. With VoiceBox it also counts the built-in presets add_voice can save as profiles. Check speech_setup first.

    View tool JSON
    {
      "name": "list_voices",
      "kind": "answer",
      "impl": "imperative",
      "description": "The voices the chosen voice provider can speak with, grouped by language, each with the id to pass as voice to add_voice_over — and which voice and language the person has selected. With VoiceBox it also counts the built-in presets add_voice can save as profiles. Check speech_setup first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string",
            "description": "Only voices of this language, as an ISO code such as es or en."
          }
        }
      }
    }
    add_voiceAction

    Give the chosen voice provider a new voice and select it. VoiceBox: one of its built-in presets ("kokoro/ef_dora", from list_voices) saved as a profile, or a clone of a recording in the library — fromSourceId plus referenceText, the words said in it (the recording’s transcript is used when there is one). ElevenLabs: an instant clone of a recording, which sends the audio there. Returns the voice id for add_voice_over.

    View tool JSON
    {
      "name": "add_voice",
      "kind": "act",
      "impl": "imperative",
      "description": "Give the chosen voice provider a new voice and select it. VoiceBox: one of its built-in presets (\"kokoro/ef_dora\", from list_voices) saved as a profile, or a clone of a recording in the library — fromSourceId plus referenceText, the words said in it (the recording’s transcript is used when there is one). ElevenLabs: an instant clone of a recording, which sends the audio there. Returns the voice id for add_voice_over.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "What to call the voice."
          },
          "preset": {
            "type": "string",
            "description": "VoiceBox only: \"<engine>/<voice id>\" from list_voices, e.g. \"kokoro/em_alex\"."
          },
          "fromSourceId": {
            "type": "string",
            "description": "A library recording with sound (filename from list_media) to clone."
          },
          "referenceText": {
            "type": "string",
            "description": "What is said in that recording, for VoiceBox. Default: its transcript."
          },
          "language": {
            "type": "string",
            "description": "ISO code of the voice’s language, e.g. es. Default: the preset’s, else the panel’s choice."
          }
        },
        "required": [
          "name"
        ]
      }
    }
    time_scriptAction

    How long a script takes to say, and when each word lands, without recording anything or sending it anywhere. Uses the computer’s own voice silently, so it always works, costs nothing, and is the cheap way to check a script fits a shot before paying anyone to voice it.

    View tool JSON
    {
      "name": "time_script",
      "kind": "act",
      "impl": "imperative",
      "description": "How long a script takes to say, and when each word lands, without recording anything or sending it anywhere. Uses the computer’s own voice silently, so it always works, costs nothing, and is the cheap way to check a script fits a shot before paying anyone to voice it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The script to time."
          }
        },
        "required": [
          "text"
        ]
      }
    }
    render_timelineAction

    Render the whole timeline to a file: animation and caption layers are rendered to alpha first, then ffmpeg composites them over the footage and mixes the audio. mp4 = H.264+AAC; mov = ProRes 4444+PCM with alpha; webm = VP9+Opus. Takes seconds to minutes; run check_timeline first.

    View tool JSON
    {
      "name": "render_timeline",
      "kind": "act",
      "impl": "imperative",
      "description": "Render the whole timeline to a file: animation and caption layers are rendered to alpha first, then ffmpeg composites them over the footage and mixes the audio. mp4 = H.264+AAC; mov = ProRes 4444+PCM with alpha; webm = VP9+Opus. Takes seconds to minutes; run check_timeline first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "format": {
            "type": "string",
            "enum": [
              "mp4",
              "mov",
              "webm"
            ],
            "description": "Default mp4."
          },
          "quality": {
            "type": "integer",
            "description": "CRF for mp4/webm, lower is better. Default 20."
          },
          "timelineId": {
            "type": "string",
            "description": "Open this timeline first (id from list_timelines)."
          }
        }
      }
    }
    save_frameAction

    Grab one frame into the asset library as a PNG: "footage" takes the exact source frame of the footage under the playhead (or timeSeconds); "composite" takes the whole stacked frame — footage, overlays, captions. Use it in a clip with <img src="/assets/NAME">: freeze frames, before/after, a still to draw over.

    View tool JSON
    {
      "name": "save_frame",
      "kind": "act",
      "impl": "imperative",
      "description": "Grab one frame into the asset library as a PNG: \"footage\" takes the exact source frame of the footage under the playhead (or timeSeconds); \"composite\" takes the whole stacked frame — footage, overlays, captions. Use it in a clip with <img src=\"/assets/NAME\">: freeze frames, before/after, a still to draw over.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timeSeconds": {
            "type": "number",
            "description": "Timeline time. Defaults to the playhead."
          },
          "source": {
            "type": "string",
            "enum": [
              "footage",
              "composite"
            ],
            "description": "Default \"footage\"."
          },
          "name": {
            "type": "string",
            "description": "A name for the asset file, e.g. \"L4-ultima-fila\". Default: the footage name and time."
          },
          "timelineId": {
            "type": "string",
            "description": "Open this timeline first (id from list_timelines)."
          }
        }
      }
    }
    set_keyframeAction

    Make a value different at two moments and the editor draws the line between: where the layer sits (offsetX, offsetY), how big it is (scale) and how solid (opacity). Times are the *item's own*, counted from its start, so trimming its head does not re-time the move inside it. Leave value out to key whatever the item is at right now. Rotation cannot be keyframed — turning changes the size of the box a layer needs, and a box that changed size every frame would make the placement arithmetic time-varying everywhere.

    View tool JSON
    {
      "name": "set_keyframe",
      "kind": "act",
      "impl": "imperative",
      "description": "Make a value different at two moments and the editor draws the line between: where the layer sits (offsetX, offsetY), how big it is (scale) and how solid (opacity). Times are the *item's own*, counted from its start, so trimming its head does not re-time the move inside it. Leave value out to key whatever the item is at right now. Rotation cannot be keyframed — turning changes the size of the box a layer needs, and a box that changed size every frame would make the placement arithmetic time-varying everywhere.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "property": {
            "type": "string",
            "enum": [
              "offsetX",
              "offsetY",
              "scale",
              "opacity"
            ]
          },
          "atSeconds": {
            "type": "number",
            "description": "Where, in the item's own time (0 = its start). Defaults to the playhead."
          },
          "value": {
            "type": "number",
            "description": "What it should be there. Defaults to what it is now."
          },
          "ease": {
            "type": "string",
            "enum": [
              "ease",
              "linear",
              "hold"
            ],
            "description": "How it leaves this key. ease slows in and out, linear is a straight line, hold stays put until the next. Default ease."
          }
        },
        "required": [
          "itemId",
          "property"
        ]
      }
    }
    list_keyframesAnswer

    Every keyframe on an item, per property, in the item's own time.

    View tool JSON
    {
      "name": "list_keyframes",
      "kind": "answer",
      "impl": "imperative",
      "description": "Every keyframe on an item, per property, in the item's own time.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    clear_keyframesAction

    Remove keyframes from an item — one property, or all of them. It goes back to standing still at whatever its plain values are.

    View tool JSON
    {
      "name": "clear_keyframes",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove keyframes from an item — one property, or all of them. It goes back to standing still at whatever its plain values are.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "property": {
            "type": "string",
            "enum": [
              "offsetX",
              "offsetY",
              "scale",
              "opacity"
            ],
            "description": "Leave out to clear every property."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    freeze_frameAction

    Hold one frame: save it to Assets and place it on the timeline as a still. A freeze is a picture of a shot rather than a property of it, so what you get is an ordinary image item — it trims, moves, scales, turns and renders like any other.

    View tool JSON
    {
      "name": "freeze_frame",
      "kind": "act",
      "impl": "imperative",
      "description": "Hold one frame: save it to Assets and place it on the timeline as a still. A freeze is a picture of a shot rather than a property of it, so what you get is an ordinary image item — it trims, moves, scales, turns and renders like any other.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "atSeconds": {
            "type": "number",
            "description": "Which moment. Defaults to the playhead."
          },
          "source": {
            "type": "string",
            "enum": [
              "composite",
              "footage"
            ],
            "description": "composite = everything the preview shows; footage = the raw shot with no overlays. Default composite."
          }
        }
      }
    }
    add_markerAction

    Pin a moment on the timeline — a beat to cut on, a mistake to come back to, the top of a section. Markers belong to the timeline rather than to any item, because what they usually mark is the join between two, and a note on either would go when that one was trimmed. Dropping one on a moment that already has a marker renames it instead of stacking two.

    View tool JSON
    {
      "name": "add_marker",
      "kind": "act",
      "impl": "imperative",
      "description": "Pin a moment on the timeline — a beat to cut on, a mistake to come back to, the top of a section. Markers belong to the timeline rather than to any item, because what they usually mark is the join between two, and a note on either would go when that one was trimmed. Dropping one on a moment that already has a marker renames it instead of stacking two.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "atSeconds": {
            "type": "number",
            "description": "Where. Defaults to the playhead."
          },
          "label": {
            "type": "string",
            "description": "What happens here."
          },
          "timelineId": {
            "type": "string",
            "description": "Id from list_timelines. Defaults to the open timeline."
          }
        }
      }
    }
    list_markersAnswer

    Every marker on a timeline, in time order.

    View tool JSON
    {
      "name": "list_markers",
      "kind": "answer",
      "impl": "imperative",
      "description": "Every marker on a timeline, in time order.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timelineId": {
            "type": "string",
            "description": "Id from list_timelines. Defaults to the open timeline."
          }
        }
      }
    }
    delete_markerSensitive Action

    Remove a marker by its id (from list_markers).

    View tool JSON
    {
      "name": "delete_marker",
      "kind": "transact",
      "impl": "imperative",
      "description": "Remove a marker by its id (from list_markers).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "markerId": {
            "type": "string"
          },
          "timelineId": {
            "type": "string",
            "description": "Id from list_timelines. Defaults to the open timeline."
          }
        },
        "required": [
          "markerId"
        ]
      }
    }
    cross_dissolveAction

    Turn the cut after an item into a cross dissolve. One track holds one item at a time, so the next item is lifted to the track above and pulled back over this one, and both get the matching half of the fade. The result is two ordinary items with ordinary dissolves — they trim, move and delete as such.

    View tool JSON
    {
      "name": "cross_dissolve",
      "kind": "act",
      "impl": "imperative",
      "description": "Turn the cut after an item into a cross dissolve. One track holds one item at a time, so the next item is lifted to the track above and pulled back over this one, and both get the matching half of the fade. The result is two ordinary items with ordinary dissolves — they trim, move and delete as such.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "itemId": {
            "type": "string",
            "description": "Item id from get_timeline."
          },
          "seconds": {
            "type": "number",
            "description": "How long the dissolve lasts. Default 0.6."
          }
        },
        "required": [
          "itemId"
        ]
      }
    }
    undo_editAction

    Undo the last edit to a timeline (any tool that changed it, or a hand edit). Each timeline has its own history, up to 100 steps.

    View tool JSON
    {
      "name": "undo_edit",
      "kind": "act",
      "impl": "imperative",
      "description": "Undo the last edit to a timeline (any tool that changed it, or a hand edit). Each timeline has its own history, up to 100 steps.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }
    redo_editAction

    Redo the last undone timeline edit.

    View tool JSON
    {
      "name": "redo_edit",
      "kind": "act",
      "impl": "imperative",
      "description": "Redo the last undone timeline edit.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timelineId": {
            "type": "string",
            "description": "Work in this timeline (id from list_timelines) instead of the open one. It need not be open; the view stays where it is."
          }
        }
      }
    }