# Resolve Edit

> Editing, cutting, trimming, pacing, and timeline restructuring in the DaVinci Resolve MCP. Apply when duplicating/moving clips, copying ranges, building variants, tightening or restructuring a cut, editing selects, or generating an editorial changelist/turnover — live in a running Resolve OR offline against .drt timeline files. Routes to the live edit tools, the offline editorial tools, and the project's editorial craft guidance.

- Skill: `samuelgursky/resolve-edit-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add samuelgursky/resolve-edit-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/samuelgursky/resolve-edit-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: samuelgursky (https://skillmd.com/u/samuelgursky)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/samuelgursky/resolve-edit-2

---


# Resolve Timeline Edit
Bridges editorial *craft* to this repo's *tools*. Open the right manual; don't
re-derive it here.

- **Craft / story** — `docs/guides/editorial-decision-guide.md`. The global
  `editor` / `assistant-editor` skills add editorial philosophy and cutting-room
  practice; use them for *why to cut*, not tool mechanics.
- **Live tool mechanics** — `docs/kernels/timeline-edit-kernel.md` (the `timeline`
  edit-kernel boundary: duplicate/copy/move, range ops, item-state copy).
- **Offline timeline / changelist** — `resolve-advanced/README.md` → `drt`
  (timeline file authoring) and `editorial` (interchange + turnover).

## Two servers

| Job | Server | Tools |
|---|---|---|
| Restructure a **running** timeline | `davinci-resolve` (Python, live) | `timeline` (edit kernel), `timeline_item`, `edit_engine`, `timeline_markers` |
| Author/diff a `.drt` **file**, or parse/compare editorial interchange with **no Resolve open** | `davinci-resolve-advanced` (Node) | `drt`, `editorial` |

## What this build cannot do (check before you offer it)

The scripting API changes per **patch** release, so "Resolve 21" is not a usable
label. Read `resolve_control get_version` → `build.unavailable_on_this_build`
before offering a gated surface; `check_version_support` asks about one named
symbol. Gated in *this* domain:

| Surface | Needs | If absent |
|---|---|---|
| `Timeline.GetSelectedClips` | 21.0.4 | No selection readback. Identify clips by track/index or id instead — this repo's selection helper duck-probes three names, so it degrades to "no selection" rather than erroring |
| `TimelineItem.SetName` | 20.2 | Clip names are read-only from a script |

An empty `unavailable_on_this_build` means **nothing recorded is missing**, not
that everything exists — most of the API has never been version-bisected. A
symbol with no gate returns `unknown`, which means probe it. Probe with
`name in dir(obj)`, never bare `hasattr`: on a Resolve object `hasattr` returns
`True` for every name, real or invented, so it can only say yes.

Distinguish *gated* from *absent*. A gated surface arrives with a newer build;
an absent one never does, and upgrading will not help. **Clip speed / retime is
absent on every build** — see the edit-kernel essentials below before you offer
`set_retime` for it.

## Live edit-kernel essentials

- Duplicate/relocate: `duplicate_clips` (modes `same_time`/`offset`/
  `at_playhead`/`track_above`/`after_source`/`next_gap`), `copy_clips` (alias),
  `move_clips` (duplicate-then-delete). `include_linked=True` carries linked audio.
- Ranges: `copy_range`, `duplicate_range`, `overwrite_range`, `lift_range`.
  **No public razor/split** — partial overlaps in `lift_range` are blocked unless
  `allow_partial_item_delete=True` (whole-item delete, not a trim).
- Item state copy: `copy_properties` (transform/crop/composite/audio/retime/
  markers/flags/grades/takes/keyframes …); scope with a group list.
- **Reading the user's selection is best-effort and version-dependent.** The
  selection helper duck-probes three method names; the documented one,
  `Timeline.GetSelectedClips`, is **21.0.4+** (issue #131), so on older builds
  selection resolves by luck or not at all. Never build a destructive operation
  on "the selected clips" without reading back what you actually got — an empty
  or partial selection is indistinguishable from a small one.
- **There is no clip-speed API at any version.** `set_retime` sets retime
  *quality* only (`RetimeProcess`, `MotionEstimation`) and returns `True` for
  doing so, which reads as if the retime succeeded. Setting a % speed, reversing
  a clip, and speed ramps are all unreachable — `SetProperty('Speed'|'PlaybackSpeed'|
  'RetimeSpeed'|'ClipSpeed')` returns `False` and the matching `GetProperty`
  returns `None` on every build measured. Say so and route the user to the UI;
  do not offer `set_retime` as if it answered the question (issue #132).
- **Routing to the UI is where issue #132 actually went wrong — and it was not
  a tool lie.** Having been told to hand off, the assistant improvised the
  handoff: it sent the user hunting for a dropdown "in the lower left of the
  clip" and never mentioned the keyframe tray. That direction came from nowhere
  in this repo. **This repo verifies API behavior, not UI geography, and has no
  mechanism to version-guard a UI claim** — Resolve's controls move between
  builds, pages and layouts, and every ledger entry here is stamped with the
  build it was measured on precisely because unstamped claims rot. So:
  **never improvise UI geography.** Say *what* the user needs to do ("set the
  clip's speed / build the speed ramp in Resolve's own retime controls") and say
  plainly that you cannot see their screen. Do **not** invent where a control
  sits, what it looks like, which corner of a clip to click, or a menu path or
  keyboard shortcut recalled from general knowledge — an invented location costs
  the user more than "I don't know where it is on your build" ever does, and it
  reads as authoritative because everything else you told them was measured.
  **The line is improvised vs. written down here.** A UI pointer that already
  exists in these skills (e.g. the playback-frame-rate path in
  `resolve-rough-cut`) was authored and reviewed deliberately — use it verbatim.
  If no pointer exists, that is not an invitation to supply one: name the
  operation and point at Blackmagic's manual for their build. The same rule
  covers every other "do it in the UI" handoff in these skills.
- `edit_engine` drives higher-level selects/tighten/swap flows
  (plan → confirm → execute); tighten variants can carry audio via `keep_ranges`
  mirror / `include_audio`. For a full dead-air pass over **one long single-take
  recording** — transcribe → plan → review → execute, with the source/record
  coordinate trap spelled out — use the `resolve-tighten-recording` skill.

## Show the gaps before cutting them (`edit_engine`)

- **`plan_dead_space_markers(timeline_name?, tightness?)`** — the review gate.
  Same calibrated detection as `plan_silence_ripple`, but it proposes **markers**
  instead of assembling a variant, so a human sees every gap before agreeing to
  lose it. **Use this whenever the ask is "mark the dead space so I can review
  and approve"** — that is a request for this verb, not for a tighten. Red =
  confident, Yellow = the gate only just cleared its separation floor. Nothing
  is written; pair the marker specs with `timeline_markers`.
- **`tightness`** on the dead-space planner: `generous` (default) | `balanced` |
  `tight`. Default is deliberately the loosest. A first assembly is supposed to
  be long — trimming a generous cut is fast and visible, while recovering
  material the machine already discarded is slow and invisible. Move to `tight`
  only when the editor asks for it.
- Guard bands are floored regardless of tightness: a removed gap always leaves
  frames before it (the outgoing word's decay) and after it (the incoming word's
  attack). `tight` removes *more gaps*, never *more speech*.

## Word-level editing and spoken search (`edit_engine`)

Silence-driven tightening cannot remove an audible "um" mid-phrase or a
stammered restart. These work on the words instead and are complementary to
`plan_silence_ripple`, not a replacement.

- **`plan_transcript_tighten(clip_ref)`** — fillers, false starts and long
  pauses, at word boundaries. Emits the same `keep_ranges` shape the variant
  assembler already takes, and **every removal states its reason**, so the plan
  can be argued with rather than only accepted. False starts are a flagged
  heuristic: tight repeats only, so "no, no, no" as emphasis survives.
- **`search_spoken_content(query, mode)`** — phrase / all_words / regex across
  every transcribed clip, returning timestamped hits with context plus
  `selects` (in/out with handles). A *lexical* axis; `find_similar` is the
  semantic-visual one. Use both — a shoot should be searchable either way.
  Deterministic order (clip name, then time), so an identical search gives an
  identical selects list.
- Needs `transcript_words`: run transcription, then strata backfill. Both
  actions say so rather than returning an empty plan.

## Offline editorial (`editorial` actions)

- `parse_interchange` — EDL / OTIO / XMEML (AAF = an honest refuse, not a fake).
- `turnover_changelist` — moved / retimed / trimmed / replaced / new / gone between
  two cuts PLUS the junction diff (transitions added / dropped / changed, fade
  in/out, span deltas — carrier lines and BL fade legs never read as sources),
  with timing silent-lie guards (it flags what it cannot verify).
- `conform_manifest`, `marker_roundtrip`.

Use these to answer "what changed between v3 and v4" or to hand a conform an
accurate change list **without** opening either timeline in Resolve. For carrying
a *conform* across a re-edit, see the `resolve-conform` skill.

## Source-media safety (AGENTS.md)

Edit operations reference existing Media Pool items — they never transcode,
render, proxy, or create derivatives of source media. Keep it that way. Treat
generated probe reports as local scratch artifacts, not committed files.

