I build CutVoke, an open-source (MIT) local video editor that Claude Code / Codex can drive over MCP. This post is about one feature and its limits.

A request that keeps coming up in editing threads this month is some version of:

"Adapting finished edits from 16:9 to 9:16, 1:1, 4:5, etc. Reframing shots and repositioning graphics for different aspect ratios."

And from a Dev.to post on cutting Shorts from long talks (kelvaro):

"most of the clock time is not creative. It is the same checklist"

"Reframe to 9:16" is on that checklist. The usual way to do it is to duplicate the project file, change the canvas, nudge everything, and export. Now you have two projects that drift apart the moment you fix a typo in one of them.

Versions live inside one project

In CutVoke a "production version" is another sequence in the same project, not another file.

  • sequence.duplicate copies the complete editable sequence and can set width, height, fps and reframe in the same step. Internal object IDs are regenerated and references updated, nested sequences included.
  • sequence.configure changes the active sequence's real canvas, frame rate and framing.
  • sequence.switch moves between them.

Canvas sizes are even numbers from 2 to 8192, frame rates 1–240. Changing the frame rate keeps absolute time, so clip speed doesn't change. Duplicating, configuring and switching are all undoable, and the original 16:9 sequence stays as it was.

Three framing modes, and what they really do

reframe takes one of three values:

  • contain: keep the whole picture (letterbox/pillarbox).
  • cover: fill the canvas and crop from the centre.
  • stretch: the old default, kept for older projects.

Positions and pixel font sizes are scaled to the new canvas; caption font size, stroke and shadow are scaled too, and default caption size is still picked from the canvas.

The honest part: cover is a geometric centre crop. It is not face detection and not speaker tracking. If your speaker sits on the left third, a centre crop will cut them. For two people in frame, contain or a layout you build yourself on extra tracks is the safer choice. CutVoke has no ready-made "two boxes stacked vertically" template; that is manual track positioning.

Letting the agent do the boring part, and look at it

Over MCP, the flow an agent can follow is roughly:

  1. sequence.duplicate with 1080×1920 and reframe: cover (or contain).
  2. preview_frames to get up to 6 real rendered frames, captions included, and check headroom, hands, faces and subtitles.
  3. Adjust the supported transforms/keyframes where the crop is wrong.
  4. Leave the edit for a human to open and fix by hand on the same timeline if the agent's crop choice is off.

The agent doesn't get taste for free. What it gets is pixels to check before anyone exports.

Queue every version at once

With an output path prefix set, "queue all versions" submits one export job per sequence, with the sequence ID in the file suffix. Each job freezes that sequence's canvas, frame rate, framing and timeline when it is queued, so editing afterwards doesn't change a job that's already submitted. export.enqueue and POST /projects/{id}/exports both accept a sequenceId, so you don't have to switch the active sequence first. Agents poll the job with export_job and wait the returned pollAfterSeconds between checks.

Exports re-encode (libx264, or NVENC when available). This is not a lossless stream-copy tool.

What this doesn't solve

  • No subject/face-tracking reframe (centre crop only).
  • No automatic highlight or "best 30 seconds" picking.
  • No layout templates for split-screen verticals.
  • Desktop only (Windows/macOS/Linux).

If the versions problem is where your week goes, the docs for this part are in docs/user/PRODUCTION_VERSIONS_INTERCHANGE.md in the repo: https://github.com/frankShan001/CutVoke. Questions and "this broke on my footage" reports are welcome in the comments.