chukcut-cli edits chukcut projects without the window. Use it from a shell, a
script, a build pipeline or an AI agent. Every command calls the same engine
functions as the app. A project that the CLI writes is a project that the app
opens, and the reverse.
chukcut-cli mcp gives the same operations to an MCP client, for example
Claude Code. DaVinci Resolve 21.1 made its scripting API a Studio-only (paid)
feature. In chukcut, scripting is free and part of the build.
cargo build --release -p chukcut-cli
./target/release/chukcut-cli --helpThe CLI uses the same system packages as the app (see the README). It has
offline transcription (whisper.cpp) by default. --no-default-features builds
it without whisper.cpp. On a machine with nvcc the build also makes the
CUDA helper chukcut-whisper-cuda next to it, and local transcription runs
on the NVIDIA GPU (decision 0036).
Copy the binary to a folder on your PATH, for example ~/.local/bin, to use
it as chukcut-cli.
Each command:
- opens the project file,
- applies the operation through the engine's command layer (the same
functions the app calls; every edit is an
EditCommandwith an undo), - validates the document,
- saves it with a temporary file and a rename, so a crash cannot leave half a file.
When the operation fails, or when the result does not validate, the CLI does not write the file. The file keeps its last good state.
--dry-run runs the command and does not save. Use it to see what an edit
does.
info lists every lane and every clip. Each clip has a ref and an id:
lane 0 "Video 1" (video)
0:0 9967430b video 0.000 – 2.000 a.mp4 [graded]
0:1 4b29c932 video 2.000 – 4.000 a.mp4
lane 2 "Text 1" (text)
2:0 bd493650 title 0.500 – 2.500 Hello
| To name a… | write |
|---|---|
| clip | its full id, a unique prefix of 4 or more characters (9967430b), or lane:index (0:1 is the second clip on lane 0, in time order) |
| lane | its index (0), its name ("Video 1", any case), or its id |
| imported media | its id, its file name (a.mp4), or its path |
| effect on a clip | its index in the clip's stack (0), its kind (glow), or its id |
A lane:index ref changes when clips move. An id never changes. Scripts that
do many edits must keep the ids that the commands return.
Lanes are numbered from the bottom of the stack. A higher lane paints over a lower lane.
Times are on the timeline, unless the option says otherwise.
| You write | It means |
|---|---|
2.5 or 2.5s |
2.5 seconds |
250ms |
250 milliseconds |
1500000us |
microseconds, the engine's own unit |
1:02.5, 01:02:03.25 |
minutes:seconds, hours:minutes:seconds |
45f |
45 frames at the project's frame rate |
In JSON (batch files, MCP), a number is seconds and a string can use all the forms above.
#rrggbb, #rrggbbaa, #rgb, r,g,b or r,g,b,a with values from 0 to 1,
or a name: white, black, red, green, blue, yellow, transparent.
Positions are in canvas units. 0,0 is the centre. 1 is the edge: x 1 is
the right edge, y 1 is the top edge. Positions stay correct when the canvas
size changes.
Without --json, the CLI prints one line for a person. info, catalog,
captions list and batch print a short table.
With --json, stdout gets one JSON document and nothing else:
{
"ok": true,
"op": "split",
"message": "split at 2.000 s; 1 new clip(s)",
"saved": true,
"data": { "at": 2.0, "created": [ { "id": "4b29c932-…", "ref": "0:1", "start": 2.0, … } ] }
}On a failure:
{ "ok": false, "error": { "kind": "refused", "code": 1, "message": "nothing to split: no clip crosses the playhead" } }Progress goes to stderr: a line that updates on a terminal, one line for each
step in a pipe, and JSON lines ({"progress": 0.42, "label": "Encoding frame 88 of 210 (31 fps)"})
with --json.
-v and -vv show engine diagnostics on stderr. RUST_LOG overrides them.
| Code | Kind | Meaning |
|---|---|---|
| 0 | Done | |
| 1 | refused |
The engine refused the edit: a collision, a value out of range, nothing to undo. Nothing was saved. |
| 2 | usage |
The arguments are wrong: an unknown clip, option or name. |
| 3 | project |
The project file cannot be read, written or created. |
| 4 | invalid |
The edit made the document inconsistent, or validate found errors. Nothing was saved. |
| 5 | render |
An export or a frame render failed (for example, no GPU). |
- The app's working copy. The app writes a crash-recovery copy of the open project after every edit. The CLI turns this off. A CLI run cannot make the app "restore" a document that it did not have.
- The preview cache. The app can run at the same time.
- Proxies. The CLI does not start proxy encodes.
The CLI reads your settings: the caption panel's transcriber, your cloud
accounts and the LUT library. It uses the same XDG folders as the app
(~/.config/chukcut, ~/.cache/chukcut, ~/.local/share/chukcut).
Every command except catalog and mcp takes the project file first. The
global options --json, --dry-run and -v go anywhere on the line.
Makes an empty project with one video lane and one audio lane.
| Option | Default | |
|---|---|---|
--name |
the file name | |
--width, --height |
1080, 1920 | canvas in pixels |
--fps |
30 | |
--force |
replace a file that exists |
The first video that you import into an empty project sets the canvas shape
and the frame rate, as in the app. A 16:9 clip makes a 1920x1080 project. Use
configure after the import to change it.
chukcut-cli new reel.chukcutThe summary: canvas, frame rate, duration, each lane with its clips (ref, id,
kind, source, start, end, in, out, speed, volume, transform, effects, grade,
transition, animation, keyframes), the imported media, validation issues and
the undo state. --full gives the complete project document instead.
chukcut-cli info reel.chukcut --json | jq '.data.tracks[0].clips[].id'Lists warnings (for example, missing media) and errors (an inconsistent document). Exit code 4 when there are errors.
--name, --width, --height, --fps, --background COLOUR. One undo
step. A new frame rate does not move clips: all times are in microseconds.
chukcut-cli configure reel.chukcut --width 1080 --height 1920Adds video, image or audio files to the project's media. With --append, it
also puts each file at the end of the first lane of its kind. Import is not an
undo step (the same as in the app). Importing the same file again gives the
same media id.
chukcut-cli import reel.chukcut take1.mp4 take2.mp4 music.mp3 --appendLists what you can use. Does not need a project. --search and --filter
narrow the lists that take them (see the table).
| Kind | Lists |
|---|---|
effects |
effect ids and their parameters (ranges, defaults, choices) |
audio |
audio effect ids and their parameters (ranges, defaults, units) |
transitions |
the built-in kinds and the library presets |
animations |
clip presets (which slot each one fits), text presets, easings |
grade |
every grade control name and its resting value |
presets |
export presets, built in and your own (presets PROJECT also shows how each fits a project) |
hardware |
hardware encoders, and which ones work on this machine |
models |
local transcription models, and which ones are downloaded |
luts |
.cube files in the LUT library |
fonts |
font families that the text renderer can draw |
masks |
mask shapes, mask operations and the mask values you can set |
blend |
blend modes |
title_styles |
title styles for title style (id, name, category, sample words) |
title_templates |
text templates for title template (a style and an animation) |
layouts |
split-screen layouts and picture-in-picture corners |
speed_presets |
speed-ramp presets for speed-curve, with their shapes |
accounts |
the cloud accounts that the app has, and what each one can do; never a key |
looks |
chukcut's own looks for look (writes them into the LUT library the first time) |
emoji |
emoji stickers for sticker --emoji; --search a name, --filter a style (fluent3d, fluent_flat, noto) |
icons |
icons for sticker --icon; --search is necessary |
animated_emoji |
Noto Animated Emoji (Lottie, CC BY 4.0) for sticker --animated; --search a name or tag |
music |
the curated tracks (--filter a mood: Upbeat, Chill, Funny, Cinematic, Calm), or --search all of Incompetech |
sfx |
the sound-effect packs; --filter PACK lists the sounds of one pack (downloads it the first time), --search narrows them |
font_catalogue |
Fontsource families; --search a name, --filter a category (sans_serif, serif, display, handwriting, monospace, popular) |
fonts_installed |
the families that the library downloaded |
fonts_system |
every family that the text renderer can draw now |
library_settings |
the library's settings (where font previews come from) |
providers |
the cloud provider kinds and what each one can do |
fal_actions |
the fal.ai actions for cloud fal |
voices |
the voices of a speech account (--filter ACCOUNT, or the first speech account) |
machine |
this machine's GPU, hardware decoders and encoders |
settings |
the app's settings |
cache |
how much the cache and the proxies use |
recent |
the start screen's recent projects |
The library kinds download a catalogue the first time and keep it for a week. Without the network, they use the old copy or fail with exit code 1.
Puts imported media at the end of the first unlocked lane of its kind. A still image gets 3 seconds.
Puts imported media on the timeline at a time.
| Option | |
|---|---|
--track LANE |
the lane; it must be the right kind and free |
--duration TIME |
the length; default is the rest of the media |
--from TIME |
where in the media the clip starts reading |
Without --track, the CLI uses the first lane of the right kind that has
space. When no lane has space, it adds a lane above the last lane of that kind.
# A 2-second cutaway from 10 s into broll.mp4, over the main clip at 4 s.
chukcut-cli place reel.chukcut broll.mp4 --at 4 --from 10 --duration 2Cuts a clip in two at a time. Without --clip, it cuts every unlocked clip
under that time (the app's split at the playhead). Linked audio is cut with
its picture. The result lists the new clips.
Removes clips. --ripple moves the later clips on the lane to the left to
close the gap. When a tracked overlay follows a clip that you delete, the CLI
first bakes the overlay's motion to keyframes, so the overlay keeps its motion.
Moves a clip. The CLI refuses a place where the clip overlaps another clip.
| Option | |
|---|---|
--head TIME |
move the start edge to this timeline time |
--tail TIME |
move the end edge to this timeline time |
--duration TIME |
give the clip this length; the start stays |
--ripple |
later clips on the lane move with the clip's end; a head trim keeps the start in place |
The CLI clamps the edges to the media and to a minimum of one frame, as the app does when you drag.
chukcut-cli trim reel.chukcut 0:0 --head 0.4 --tail 3.2 --ripple--x, --y (position), --scale, --rotation (degrees, clockwise),
--opacity (0 to 1), --flip-h true|false, --flip-v true|false,
--volume (linear gain), --speed (playback rate). Transform and volume are
one undo step. Speed keeps the part of the file that the clip shows: speed 2
halves the clip's length and pulls the later clips in.
Gives the clip a name of its own. The timeline shows it instead of the file
name. An empty name ("") clears it.
link makes two or more clips move, trim and delete as one (as a picture and
its sound do after import). unlink breaks the link of a clip.
Adds an empty lane of video, audio, text, sticker or effect, directly
above the last lane of that kind. The result gives its id and index. A
headline and a subtitle at the same time:
chukcut-cli title add reel.chukcut "Day 1" --at 0.5 --duration 4
chukcut-cli lane-add reel.chukcut --kind text
chukcut-cli title add reel.chukcut "Lisbon" --at 0.5 --duration 4 --track "Text 2" --y -0.6Copies the position, scale, rotation, opacity, speed, volume, crop and grade
of --from onto the other clips. One undo step. The linked partners of the
target clips do not change.
Holds the frame of a video clip. The CLI cuts the clip at --at, puts a still
of that frame between the two parts, and moves the later clips on the lane and
on its linked lanes to the right. --duration is the length of the still
(default 3 s). One undo step. The result gives the still as still.
chukcut-cli freeze reel.chukcut 0:0 --at 2.4 --duration 1.5Gives a clip a speed ramp, changes it, or removes it. Use one of:
| Option | |
|---|---|
--preset NAME |
montage, hero, bullet, jump_cut, flash_in or flash_out (catalog speed_presets) |
--point TIME=SPEED |
a point of your own; can repeat. TIME is the time in the clip's media from its in point, at normal speed. SPEED is from 0.1 to 10 |
--remove |
go back to the clip's constant speed |
The clip's length follows the curve. The later clips on its lanes move with
its end. A clip on a speed curve plays no sound (the engine has no
pitch-correct time stretch). One undo step. For a constant speed, use
set --speed.
chukcut-cli speed-curve reel.chukcut 0:2 --preset hero
chukcut-cli speed-curve reel.chukcut 0:2 --point 0=1 --point 1.2s=0.3 --point 2.5s=1Frame blending for a video clip. With blend, a frame that falls between two
frames of the file shows both, mixed by where it falls, so slow motion and
speed ramps play smoothly instead of holding each frame. With flow
("Optical flow (AI)"), it shows a frame RIFE (MIT, 22 MB, downloads on first
use) made between the two instead: one sharp picture of a moving edge where
the blend shows two faint ones. The new frames are made in the ML worker and
baked into the cache (~/.cache/chukcut/flow) before the command returns,
with progress; on the CPU it also says how long the rest will take (a GPU
bundle, ml install gpu, is 10–30 times faster). --no-bake only sets the
mode; an export bakes the frames it needs before it renders, and the app
bakes them in the background and shows the blend until they are there.
flow again on a clip that has it bakes what is missing (after a speed
change, a trim or a cleared cache). none switches blending off. Without
--mode, says what the clip has and, for flow, how many of its frames are
baked. One undo step.
chukcut-cli frame-blend reel.chukcut 0:2 --mode blend
chukcut-cli frame-blend reel.chukcut 0:2 --mode flow"Smooth slow-mo" in one step: optical flow on, and the clip slowed to 0.5x
when it is not slowed already (a clip below 1x or on a speed curve keeps
its speed), or to --speed (below 1) when given. The clips after it on its
lanes move with its end, as with set --speed. One undo step for both,
then the frames are baked as frame-blend --mode flow does.
chukcut-cli smooth-slow-mo reel.chukcut 0:2
chukcut-cli smooth-slow-mo reel.chukcut 0:2 --speed 0.25A speed effect, the app's Speed › Speed effects: a speed-curve preset and
the frame smoothing that suits it, as one undo step. montage, jump_cut,
flash_in and flash_out use frame blending; hero and bullet use
optical flow, whose frames are baked before the command returns (unless
--no-bake), as frame-blend --mode flow does. The ramp goes on every clip
linked to the clip, like speed-curve. Applying the effect a clip already
wears changes nothing. --remove takes the ramp and the smoothing off.
Without either, lists the effects and says which one the clip wears.
chukcut-cli speed-effect reel.chukcut 0:2 --effect hero
chukcut-cli speed-effect reel.chukcut 0:2 --removeMotion blur for fast moves is an effect: effect add PROJECT motion_blur --clip CLIP --set shutter=270 --set samples=12 (shutter angle 0–360°, 180 by
default; 2–32 samples, 8 by default). It averages the clip's position, scale
and rotation over the shutter; a clip that does not move is not changed.
A marker is a named time on the ruler. It does not belong to a clip. Name a
marker by its id, a unique prefix of 4 or more characters, or its index in
time order (0 is the first marker).
--label TEXT and --color (blue, the default, green, yellow,
orange, red or purple).
--at TIME moves the marker. --label changes the label; an empty label
removes it. --color changes the colour. One undo step.
Removes one or more markers as one undo step.
Lists the markers in time order: index, id, time, colour, label. It does not change the project.
chukcut-cli marker add reel.chukcut --at 12.5 --label "Drop" --color red
chukcut-cli marker set reel.chukcut 0 --at 13A project can hold several timelines. One is open at a time, and every
other command (info, split, append, export …) works on the open one.
Name a timeline by its id, a unique id prefix of 4 or more characters, its
exact name, or its index in tab order (0 is the first). A compound clip is
a clip that holds a timeline of its own. Opening one is an edit like any
other: the saved file remembers it, and later commands edit the compound
clip's lanes until compound close. export always renders the whole
timeline, even while a compound clip is open. Decision 0024.
Lists the timelines and the compound clips' sequences: index, id, name,
length, lanes, clips, how many compound clips use it, and which is open. With
--json, also the breadcrumb path into an open compound clip. It does not
change the project.
Adds an empty timeline with a video and an audio lane, and opens it.
Copies a timeline into a new one after the last. The copy's clips have new ids, their own link groups, transitions and titles.
The last timeline cannot be deleted. Deleting the open one opens its neighbour.
Opens another timeline, closing any open compound clip.
Moves the clips into a new compound clip in their place, linked partners included. The compound clip goes on the lowest video lane the clips used when it fits there, otherwise on another video lane or a new one. Prints the new clip's id.
Closes the open compound clip, or with --all every open level.
Puts a compound clip's clips back on the timeline in its place, cut at its edges. A compound clip at another speed, or on a speed curve, hands that speed to the clips inside; a clip with its own curve inside a curved compound clip is refused.
chukcut-cli compound create reel.chukcut 0:1 0:2 1:0 --name "Intro"
chukcut-cli compound open reel.chukcut 0:1
chukcut-cli split reel.chukcut --at 1.5
chukcut-cli compound close reel.chukcut
chukcut-cli timeline duplicate reel.chukcut 0
chukcut-cli timeline rename reel.chukcut 1 "Shorts cut"The MCP tools are timeline_list, timeline_new, timeline_rename,
timeline_delete, timeline_duplicate, timeline_switch, compound_create,
compound_open, compound_close and compound_flatten.
A template is a project whose picture clips are slots your media fills,
with its titles, animations, effects, transitions, looks and music already in
place. chukcut ships eleven of its own (template list); template save
adds yours under <data>/templates/user/. Decision 0022.
Lists the templates, the built-ins first: id, name, category, canvas, length and each slot's length, shape and what it accepts. Needs no project.
Writes a new project from a template, the files filling its slots in order.
A longer clip is trimmed to its slot (from its start), a shorter one is
slowed down until it spans the slot, and a picture of another shape is
cropped, centred, to the slot's shape; the slot keeps its place, length,
animation and look. Fewer files than slots leave the rest showing a numbered
placeholder. More files than slots, a file that does not read, sound only,
or a video in a photo-only slot is refused by name. The result lists each
filled slot (slowed_to when it plays slowed) and the empty ones.
Puts a template into an existing project instead, its slots filled from the
files the same way. --as timeline (the default) adds it as a new timeline
and opens it; --as compound adds it as a compound clip starting at --at
(default 0) on the first video lane with room there, or on a new lane on top.
--name names the timeline or compound clip (the template's name by
default). One undo step. The template's ids are made new, so the same
template can go in twice; a media file the project already has is shared. A
template made for another canvas shape is laid out on the project's canvas,
and the result's note says so. The result has sequence (the new timeline
or the compound clip's contents), clip (the compound clip), filled and
empty.
Lists a project's slots, in every timeline and inside compound clips: number,
clip, start (in its own sequence), length, shape, and the file in it or
(empty). The numbers run across the whole project, so two templates in one
project never both have a slot 1: each timeline's slots come together, in tab
order, its own first and then each compound clip's. When slots are in more
than one place, each line says where ("on the open timeline", "on timeline",
"in compound clip"). In JSON, number is that number, index the fill order
inside its own template, and sequence, sequence_name, in_compound,
timeline and open_timeline say where a slot is. A slot moved into a
compound clip stays a slot.
Puts a file into a slot (--clip slot:3) or into any video or photo clip,
with the same trimming, slowing and cropping. --from is where a longer clip
starts. One undo step. slot:N is the slot template slots numbers N; a
slot inside a compound clip is filled where it is, without opening it, and
its clip id (or a prefix) names it too.
Saves the project as a template of your own. The --slot clips become its
slots, in that order, --label naming them; without --slot, the slots the
project already has stay slots. Media the template still uses is copied into
it. --description and --category are optional. The project file is not
changed.
Deletes one of your own templates. A built-in cannot be deleted.
chukcut-cli template apply trip.chukcut travel-diary a.mp4 b.mp4 c.jpg d.mp4
chukcut-cli template slots trip.chukcut
chukcut-cli template replace trip.chukcut --clip slot:2 --media better.mp4 --from 3
chukcut-cli template save trip.chukcut --name "My trip look"
chukcut-cli template apply --into trip.chukcut quick-cuts e.mp4 --as compound --at 12The MCP tools are template_list and template_delete (no project),
template_apply (project is the file to write; with "into": true it is
the existing project, and as and at apply), template_apply_into (the
same on an open project, also a batch op), template_slots,
template_replace and template_save.
| Option | |
|---|---|
--set NAME=VALUE |
one control, can repeat |
--lut FILE |
attach a .cube LUT; none removes it |
--lut-intensity N |
0 to 1 |
--reset SECTION |
basic, lut, hsl, curves, wheels or all, before the --set values |
Control names: brightness, contrast, saturation, temperature,
exposure, tint, highlights, shadows, whites, blacks, vibrance,
sharpen, clarity, vignette_amount, vignette_midpoint,
vignette_feather, grain, fade, lut_intensity,
hsl_hue:BAND, hsl_saturation:BAND, hsl_luminance:BAND (bands: red,
orange, yellow, green, aqua, blue, purple, magenta), and
wheel_x:WHEEL, wheel_y:WHEEL, wheel_luma:WHEEL (wheels: lift, gamma,
gain, offset). catalog grade lists them with their resting values.
Values are in document units: exposure in stops; saturation and
contrast rest at 1 (1 is no change, contrast=0.1 makes the picture almost
flat); the others rest at 0.
All changes in one command are one undo step.
chukcut-cli grade reel.chukcut 0:0 --set exposure=0.3 --set saturation=1.15 \
--set hsl_saturation:orange=-0.2 --lut ~/luts/film.cube --lut-intensity 0.6Gives every other picture clip the grade of CLIP. One undo step.
Puts a look on the clip. LOOK is the name of one of chukcut's looks
(catalog looks), a .cube file, or none. A .cube file is checked and
copied into the LUT library first, so the clip keeps its look when the
original file goes away. The rest of the grade does not change.
chukcut-cli look reel.chukcut 0:0 "Teal & Orange" --intensity 0.7Balances a video or photo clip from its own pixels: exposure towards a
mid-grey average, white balance against the most neutral pixels, black and
white points by a levels stretch, a little vibrance when the picture is
dull. The answer is written into the ordinary grade controls (exposure,
temperature, tint, whites, blacks, vibrance), which stay editable; the
clip's other controls (contrast, a LUT, curves) stay and are part of what is
measured. --amount scales the correction (default 1). One undo step. The
data has the controls and the measurements before and after.
Grades CLIP so its colours match the clip --to, as that clip looks with
its own grade: the Lab* means and spreads through exposure, contrast,
saturation, temperature and tint, the rest of each channel's histogram
through the red, green and blue curves (not when the clip has a LUT or a
fade). --at matches the reference's frame at that timeline time instead of
the whole reference. The data reports the Lab* distance before and after.
One undo step.
chukcut-cli colour-match reel.chukcut 0:2 --to 0:0grade-preset-save PROJECT CLIP [--name NAME] [--replace] · grade-preset-apply PROJECT CLIP NAME · grade-presets PROJECT [--remove NAME]
Saves a clip's whole grade (sliders, curves, wheels, HSL, LUT, effects
such as vignette and grain) as a named preset in
$XDG_DATA_HOME/chukcut/grade-presets/ — the app's Filters › My presets.
Without --name the next free "Preset N". A preset of that name is
replaced only with --replace. grade-preset-apply gives a clip a preset's
grade (one undo step); grade-presets lists them or deletes one.
Sets one tone curve of the clip's grade. Each --point is an input level and
an output level, both from 0 to 1. Give two or more points. The engine joins
the points with a smooth curve that never overshoots. --channel is master
(the default, all colours), red, green or blue. --reset makes the
curve a straight line again. The other grade values stay. One undo step.
# A soft S-curve on the master channel.
chukcut-cli curve reel.chukcut 0:0 --point 0,0 --point 0.25,0.2 --point 0.75,0.8 --point 1,1In JSON, points is a list of [x, y] pairs or "x,y" strings.
Crops the clip's picture. --left, --top, --right and --bottom are
fractions of the source frame: left and top from 0, right and bottom up
to 1. An edge that you do not give keeps its value. --clear removes the
crop and all its keyframes. One undo step.
--at TIME sets a crop keyframe at that timeline time. The keyframe is on
all four edges. If a keyframe is already there (within half a frame), it
changes. An edge that you do not give keeps the value that the crop has at
that time. --at TIME --remove deletes the crop keyframe at that time.
When a crop has keyframes, a crop without --at is refused. One undo step
each.
chukcut-cli crop reel.chukcut 0:0 --left 0.1 --right 0.9
# Zoom in from the full picture to the middle over two seconds.
chukcut-cli crop reel.chukcut 0:0 --at 0 --left 0 --top 0 --right 1 --bottom 1
chukcut-cli crop reel.chukcut 0:0 --at 2s --left 0.25 --top 0.25 --right 0.75 --bottom 0.75Makes the clip a picture in picture: one third of the canvas wide, in a
corner with a margin, with a frame effect (round corners, a thin border, a
soft shadow). --corner is top_left, top_right, bottom_left or
bottom_right (the default). Put the clip on a lane above the main picture.
One undo step.
Puts clips into a split screen. Each clip fills one cell, in the order that
you give them. --layout:
| Layout | Clips |
|---|---|
two_rows (default) |
2, one above the other (the 9:16 reaction layout) |
two_columns |
2, side by side |
three_rows |
3 |
three_columns |
3 |
grid |
4, two by two |
chukcut-cli layout split reel.chukcut 0:0 1:0 --layout two_rowsAdds an effect (catalog effects): gaussian_blur, denoise, zoom_blur, glow,
light_sweep, shake, rgb_split, glitch, vhs, pixelate, mirror,
kaleidoscope, film_grain, halation, bloom, gate_weave, letterbox,
frame.
- With
--clip CLIP, the effect goes on the end of that clip's stack. - Without
--clip, it becomes an effect clip on an effect lane. It changes everything below it.--at(default 0),--duration(default 3 s) and--trackplace it.
--set NAME=VALUE sets parameters. The CLI checks each value against the
catalog: a number in its range, a colour, or a choice by name or index. Read
the range in catalog effects: many effects count from 0 to 100 (glow's
intensity 60 is a strong glow), not from 0 to 1.
chukcut-cli effect add reel.chukcut glow --clip 0:1 --set intensity=60
chukcut-cli effect add reel.chukcut shake --at 5 --duration 0.4
# Reduce noise, also over the frames before and after (mode spatial|temporal).
chukcut-cli effect add reel.chukcut denoise --clip 0:0 --set mode=temporal --set strength=70--set NAME=VALUE changes parameters (one undo step). --enabled false
switches the effect off and keeps its values. --at TIME sets each parameter
at that time, which makes a keyframe.
Every changed effect gets a new id (the engine never changes a material in
place). The result gives the new effect_id. The index and the kind stay the
same.
Removes the effect from the clip. To remove an effect clip, delete the clip.
Moves the effect to another place in the clip's stack. Index 0 is applied first.
Puts every parameter of the effect back to its default value.
Adds a keyframe for the parameter at that time, or removes the keyframe that
is there. To set a keyed value, use effect set --at.
Gives a clip an animation preset. --slot in|out|combo (default in).
--preset none clears the slot. --duration, --easing, --strength
change the timing and the size of the motion. catalog animations shows which
presets fit which slot.
- In and Out:
fade,slide_left,slide_right,slide_up,slide_down,zoom_in,zoom_out,pop,bounce,spin,blur,wipe_left,wipe_right,wipe_up,wipe_down,swing,shake,rise,flip,whip - Combo (a loop):
pulse,heartbeat,wobble,rock,float,jitter,rotate,flicker - Easings:
linear,ease_in,ease_out,ease_in_out,smooth,snap,back_in,back,back_in_out,elastic,bounce
Animates a title by letter, word or line. Presets: typewriter, fade,
fade_up, pop, slide_up, drop, zoom, spin, or none. Options:
--slot in|out, --unit letter|word|line,
--order forward|backward|centre|random, --duration, --overlap (0 to 1),
--easing, --strength.
A punch-in zoom: --amount (1.1 is 110 %), --pivot-x, --pivot-y,
--duration (0 is a hard punch), --easing. --clear removes it. --auto
alternates 100 % and the amount across the jump cuts next to the clip. This
hides cuts in a talking-head video.
Adds a keyframe, or changes the keyframe at that time. Properties:
position_x (or x, as in set --x), position_y (or y), scale_x,
scale_y, rotation, opacity, volume, and the crop edges crop_left,
crop_top, crop_right, crop_bottom (fractions of the source frame;
crop --at sets all four together). --value is required, except with
--remove. --easing is
hold, linear, ease_in, ease_out or ease_in_out. --at is a
timeline time. The engine keeps keyframes relative to the clip start, so they
move with the clip.
chukcut-cli keyframe reel.chukcut 2:0 --property opacity --at 0 --value 0
chukcut-cli keyframe reel.chukcut 2:0 --property opacity --at 0.5 --value 1 --easing ease_outPuts a title on the title lane. --at (default 0) and --duration (default
3 s). When the time is not free, the title moves to the next gap.
--track LANE puts it on another text lane, where it can show at the same
time as a title on the first one. lane-add PROJECT --kind text makes that
lane.
Style options (also for title set): --font, --size (canvas pixels),
--color, --bold true|false, --italic true|false,
--align left|center|right, --stroke-width, --stroke-color,
--background COLOUR|none, --shadow true|false, --x, --y.
A title with style options is two undo steps: the title, then its style.
chukcut-cli title add reel.chukcut "Day 1" --at 0.5 --size 140 --color "#ffcc00" --y 0.6--text changes the words. The style options change the look. All changes are
one undo step.
Changes only the words of a title. The style stays.
Sets the title's font family. When the text renderer does not have the
family, the CLI finds it in the Fontsource catalogue and installs it first
(this needs the network once). The result says installed: true then.
Adds a title in a style, or gives a title a new style. catalog title_styles
lists the styles.
- With
--clip CLIP, the title gets the style. It keeps its words, its size and its position. - Without
--clip, the CLI adds a new title.--at(default 0) and--trackplace it,--durationgives its length (default 3 s), and--textgives its words (default: the style's sample). The title goes where the style puts it, for example low and left for a lower third.
One undo step.
The same as title style, with a template from catalog title_templates. A
template is a style and an animation. With --clip, the title gets the
style and the animation of the template.
chukcut-cli title template reel.chukcut neon-sign --at 1 --text "Day 1"Moves a title to a cell of a 3 x 3 grid and aligns its text to match. Cells:
top_left, top, top_right, left, centre, right, bottom_left,
bottom, bottom_right. One undo step.
Copies a title: its words, style, transform, keyframes and animation. The copy
gets its own text material, so a change to one title does not change the
other. The copy starts at the end of the original, on the same lane. --at
gives another start. When the time is not free, the copy moves to the next
gap. One undo step.
Puts a transition on the cut at the start of the clip (the incoming clip).
--kind: dissolve (default), dip_to_color, wipe, slide, zoom,
blur, or a library preset from catalog transitions (gl:crosswarp, or
only crosswarp when the name is unique). --duration is shortened to what
the two clips allow. A new transition replaces the old one.
Changes the transition at the start of the clip. --duration (shortened to
what the two clips allow; the result says shortened), --easing hold|linear|ease_in|ease_out|ease_in_out,
--direction left|right|up|down (wipe, slide), --color (dip),
--softness (wipe), --zoom (zoom), and --param NAME=V[,V...] for the
parameters of a library transition.
Tracks a region of a video clip through its frames. --rect is the box in the
clip's own frame, as fractions: centre x, centre y, width, height. --at is
the timeline time where you draw the box. --direction forward|backward|both
(default both).
--overlay CLIP makes a title, sticker or other clip follow the track.
--mode position|position_scale|position_scale_rotation sets how it follows.
--tracker klt|vittrack chooses the tracker: klt (the default) needs no
model and measures rotation; vittrack runs a learned tracker in the ML
worker, holds fast and blurred objects and finds the object again after it
was hidden or left the frame, and falls back to klt when the worker cannot
run it. The command waits for the analysis to finish. The result is one undo
step.
chukcut-cli track reel.chukcut 0:0 --at 1.2 --rect 0.52,0.4,0.15,0.2 --overlay 2:0Changes how a clip follows a motion track, or the track itself; each option
is one undo step. --attach TRACK_ID --target CLIP makes the clip follow a
track track made earlier (its full track_id) in the video clip it was
made in. --mode position|position_scale|position_scale_rotation sets how it
follows. --smoothing 0..1 smooths the followed track. --bake turns the
motion into keyframes on the clip. --detach stops following and keeps the
clip where it is at --at (default: its start). --remove deletes the
followed track.
chukcut-cli track-set reel.chukcut 2:0 --smoothing 0.4 --mode position_scaleAdds, changes or removes shape masks on a clip. Each change is one undo step.
--add SHAPEadds a mask:linear,mirror,ellipse(orcircle),rectangle,starorheart. The other options then apply to the new mask.--mask REFnames the mask to change: its index (0 is the first) or its id. Without it, the command uses the mask it just added, or the only mask.--set NAME=VALUEsets a value.xandyare the centre, as a fraction of the clip from its middle (0.5 is the right or top edge, +y is up).width,heightandfeatherare fractions of the clip's shorter side.rotationis degrees, clockwise.roundness(0..1) rounds the corners of a rectangle.--at TIMEsets the values as keyframes at that timeline time.--op add|subtract|intersectsets how the mask combines with the masks before it.--invert true|false,--enabled true|false,--shape SHAPE.--removeremoves the mask.--clearremoves all masks first.
The result has compositing.masks, with each mask's index and id.
chukcut-cli mask reel.chukcut 1:0 --add circle --set width=0.8 --set feather=0.2
chukcut-cli mask reel.chukcut 1:0 --add rectangle --op subtract --set width=0.1
chukcut-cli mask reel.chukcut 1:0 --mask 0 --set x=-0.3 --at 0 --set x=0.3 --at 2Moves a mask to another place in the clip's mask order. Masks combine in
order by their op, so the order changes the result.
Keys a colour out of a clip (green screen). --color #rrggbb gives the
colour. --pick X,Y takes it from the footage under a point of the canvas
(0..1 from the top left) at --at TIME (default: the start of the clip).
--tolerance, --softness, --spill and --shrink are 0..1.
--enabled false switches the key off and keeps its values. --off removes
the key.
chukcut-cli chroma-key reel.chukcut 1:0 --pick 0.05,0.5 --spill 0.7Removes a video clip's background with a model in the ML worker.
--model people (the default) keeps people: Robust Video Matting (GPL-3.0,
15 MB), fast and stable from frame to frame. --model objects keeps the
main object of the picture (a product, a pet, a car): BiRefNet lite (MIT,
224 MB). It needs a GPU (see ml install gpu); on the CPU it refuses in
words, because one frame would take 12–25 s and 6–11 GB of memory.
--invert cuts the subject out and keeps the rest (--no-invert undoes
that); it changes how the matte is drawn, not the matte. The model and ONNX
Runtime download on first use. The setting is one undo step; the command
then bakes the clip's matte into the cache (~/.cache/chukcut/mattes) and
waits for it. Run it again on a clip that has it to bake frames that are
missing (after a trim, or a cleared cache); an export also bakes them.
--off keeps the background again; when the clip's grade or effects are
limited to its subject (apply-to), the matte stays, uncut, and running
remove-background again without --model cuts by it again.
chukcut-cli remove-background reel.chukcut 0:0
chukcut-cli remove-background reel.chukcut 0:0 --model objectsKeeps the object you point at and removes the rest, on every frame of the
clip ("Select object" in the app). The points are canvas fractions (0,0 is
the top-left corner) on the frame at timeline time --at, as render-frame
shows it: --point on the object (repeat it for a large or thin one),
--exclude on a part to leave out. MobileSAM (Apache-2.0, 45 MB) segments
that frame; the VitTrack tracker follows the object forwards and backwards
and MobileSAM draws its mask on every frame. --invert cuts the object out
instead (to remove it from the picture). One undo step, then a bake as
remove-background does. To grade or blur only the object or only the
rest without cutting anything, use apply-to after it.
chukcut-cli select-object reel.chukcut 0:0 --at 2.5 --point 0.42,0.55
chukcut-cli select-object reel.chukcut 1:0 --at 1 --point 0.5,0.5 --exclude 0.5,0.2 --invertremove-object PROJECT CLIP [--at TIME --point X,Y …] [--exclude X,Y …] [--box X,Y,W,H …] [--stroke "X,Y X,Y …" …] [--radius R] [--grow G] [--add] [--off] [--no-bake]
Removes an object from every frame of a video clip ("Remove object" in the app, Video › Enhance): LaMa (Apache-2.0, 208 MB) paints over it, in the ML worker, on this machine. Say what to remove in any mix of three ways:
- Clicks:
--at(the timeline time of the frame) and--pointon the object, canvas fractions asselect-objecttakes them,--excludeon a part to keep. MobileSAM selects it on that frame and it is followed over the clip asselect-objectfollows it (those mattes are shared). - Boxes:
--box x,y,width,height, fractions of the source picture (top-left origin), the same place in every frame: a logo, a watermark. - Strokes:
--stroke "x,y x,y …", source fractions, with--radius(a fraction of the shorter side, default 0.02), the same place in every frame.
Together they replace what the clip removed before; --add adds them
instead. --grow (default 0.012 of the shorter side) is how far the mask
reaches past the object, for its soft edge and a little of its shadow; given
alone it regrows the clip's mask. --off switches it off. Without any of
these it says what the clip has, how many frames are made and what the rest
would take on a GPU and on the CPU (estimate).
The setting is one undo step; the command then bakes the frames into the
cache (~/.cache/chukcut/enhance) and waits, with progress and, on the CPU,
how long the rest will take. An export bakes what is missing first. How the
fill is made: LaMa runs on a crop around the mask; where the object moves
on a still shot, the background the clip shows in other frames is used
instead (no model at all for a moving object on a locked-off shot); the
fill is steadied from frame to frame while the camera holds still.
chukcut-cli remove-object reel.chukcut 0:0 --at 2.5 --point 0.42,0.55
chukcut-cli remove-object reel.chukcut 0:0 --box 0.82,0.03,0.15,0.08
chukcut-cli remove-object reel.chukcut 0:0 --stroke "0.1,0.9 0.3,0.92" --radius 0.03 --addMakes a video clip's picture larger and cleaner ("Enhance quality" in the
app, Video › Enhance): Real-ESRGAN general x4v3 (BSD-3-Clause, 5 MB)
remakes every frame at 2x or 4x, at most 3840 px on the long side, and
takes out blur, noise and compression blocks on the way. For footage up to
1920 px; larger clips are refused in words. The preview and the export both
use the made frames. One undo step, then a bake as remove-object does
(the answer says what it will take; on the CPU a 1080p frame is about 15 s).
With remove-object on the same clip, the object is removed first and the
result enhanced. --scale off switches it off; without --scale it says
what the clip has.
chukcut-cli enhance-quality old-clip.chukcut 0:0 --scale 2Limits a clip's colour grade (everything in the app's Adjust tab: the
sliders, curves, wheels, HSL, LUT, vignette, grain) or its effects to the
subject of its matte or to the rest, on the clip itself, without a copy:
--grade subject grades only the person, --effects background blurs (or
glows, or pixelates) only the background. whole is the default and the way
back. The subject is the clip's matte: the one remove-background or
select-object made, or, on a clip without one, the people matte (Robust
Video Matting), made without cutting anything. The effects run over the
whole picture and are then mixed by the matte, so a background blur leaves
no dark seam around the person. Each option is one undo step; the command
then bakes the matte and waits for it. Without options, says what the clip
has. A frame whose matte is not baked yet shows the grade and the effects
on the whole clip; an export bakes what is missing first.
chukcut-cli apply-to reel.chukcut 0:0 --grade subject
chukcut-cli effect add reel.chukcut gaussian_blur --clip 0:0 --set radius=30
chukcut-cli apply-to reel.chukcut 0:0 --effects backgroundFinds the faces in a video clip — MediaPipe's face mesh (478 points per
face, Apache-2.0, 5 MB) behind the YuNet detector, in the ML worker — and
prints those at --at (default: the clip's start): box, score and the named
points retouch uses; --points adds all 478. Points are fractions of the
video frame. The landmarks are a cache file per media file
(~/.cache/chukcut/landmarks), not part of the project; the first run on a
clip analyses every frame of it. The model and ONNX Runtime download on
first use.
retouch PROJECT CLIP [--preset natural|soft|bright|sculpt] [--strength N] [--smooth N] [--eyes N] [--teeth N] [--slim N] [--off] [--no-analyse]
Retouches the faces in a video clip: smoother skin (only the face's skin,
not the eyes, brows, lips or hair), brighter eyes and teeth, a slimmer jaw.
Values are 0..100; a preset sets the four looks, --strength scales them
all, and any value can be given on its own. On a clip already retouched,
the values not given are kept. It is the retouch effect (Effects › Face in
the app), so effect set reaches it too. One undo step; then the clip's
faces are found unless --no-analyse (the app and an export find them
when they are missing). A frame without a face is drawn as it is.
chukcut-cli retouch reel.chukcut 0:0 --preset soft --slim 20follow-face PROJECT CLIP --face-of CLIP [--anchor face|eyes|forehead|nose|mouth|chin] [--mode MODE] [--face N] [--at TIME]
Makes a title, sticker or picture follow a face in a video clip. The face's
pose — the anchor point, its size and the tilt of the eyes — becomes a
motion track and the clip follows it like any tracked object, so --mode
(position, position_scale, position_scale_rotation) and track-set
(smoothing, detach, bake to keyframes) work as for track. --face picks
a face, largest first. --at is the instant the clip is where it should be
relative to the face (default its start); attaching does not move it there.
Finds the faces first if the clip has none analysed. One undo step.
chukcut-cli follow-face reel.chukcut 2:0 --face-of 0:0 --anchor forehead --mode position_scaleFinds the people in a video clip and prints the people at --at (default:
the start of the clip). The ML worker runs two models: YOLOX-tiny finds the
people, and RTMPose-m reads 17 body keypoints for each person (COCO order:
nose, eyes, ears, shoulders, elbows, wrists, hips, knees, ankles; the
person's own left before right). Both models have the Apache-2.0 licence
(48 MB and 18 MB as downloads). For each person, the command prints the id,
the score, the box and each keypoint with its confidence. A keypoint with a
confidence below 0.3 was not seen. Points are fractions of the video frame.
The id of a person stays the same from frame to frame: id 0 is the first
person that the analysis sees. The keypoints are a cache file for each media
file (~/.cache/chukcut/landmarks). They are not part of the project. The
first run on a clip analyses all its frames. The models and ONNX Runtime
download when they are first necessary.
Makes a title, sticker or picture follow a body part of a person in a video
clip. --part is one of head, shoulders, chest (default), hips,
body, left_hand, right_hand, left_elbow, right_elbow,
left_knee, right_knee, left_foot or right_foot. Left and right are
the person's own: a person who looks at the camera has the left hand on
the right of the picture. The command writes the pose of the part (its
point, its size and its angle) as a motion track. The clip follows the
track like a tracked object, thus --mode and track-set (smoothing,
detach, bake to keyframes) operate as for track. A hand turns with the
forearm; the head, the shoulders, the chest and the hips turn with the line
between the two sides. --person selects the person, from 1 (the first
person that the analysis sees). --at is the time at which the clip has the
correct position relative to the body part (default: the start of the
clip). The command does not move the clip to that position. If the clip has
no analysed people, the command finds them first. One undo step. When the
part is not visible in a frame, the follower stays where it was.
chukcut-cli follow-body reel.chukcut 2:0 --body-of 0:0 --part right_hand --mode position_scale_rotationSets how a clip blends with the lanes below it: normal, multiply,
screen, overlay, soft_light, hard_light, darken, lighten,
color_dodge, color_burn, difference, exclusion, add or subtract.
--opacity is 0..1.
The asset library of the app: emoji and icons from open sets, Incompetech
music (CC BY 4.0) and CC0 sound packs. Each file is downloaded once into the
library cache with its licence record; cloud credits then lists what needs a
credit.
Puts a sticker on an overlay lane, in the middle of the frame, for three
seconds, from --at TIME (default 0). An emoji is found by name or by the
emoji itself; --style fluent3d|fluent_flat|noto chooses the drawing.
--animated takes a Noto Animated Emoji by name, tag or the emoji itself
(catalog animated_emoji). An icon is prefix:name from catalog icons, or
a word (the first hit). --file takes a picture, or an animated sticker of
your own: a Lottie .json, or an animated GIF or WebP. Animated stickers
loop; --once plays one once and holds its last frame. One undo step.
chukcut-cli sticker reel.chukcut --emoji "red heart" --at 2.5
chukcut-cli sticker reel.chukcut --animated "party popper" --at 1 --onceMakes an animated sticker loop or play once and hold its last frame. Without
--mode, says what the clip has and how long one pass of the animation is.
One undo step.
Imports a music track by its title (or words from it) and, with --at, puts
it on the timeline. Curated tracks first, then the whole catalogue.
Imports a sound from a pack (catalog sfx, then catalog sfx --filter PACK)
and, with --at, puts it on the timeline.
The analysis commands look at the pictures or the sound of a clip. The command waits until the analysis is done and shows progress on stderr. Then the result goes into the project as one undo step.
Finds the shot changes in a video clip and marks them on the clip.
--sensitivity from 0 to 1 (default 0.5: hard cuts, not fast motion).
--split also cuts the clip at each change, in the same undo step. The result
lists the changes in timeline seconds.
Cuts the clip at the scene changes that scenes detect found. One undo step.
Removes the scene marks from the clip.
Measures the camera shake of a video clip, or of a compound clip's rendered
contents, and stabilises it. --strength from
0 to 1 (light 0.35, medium 0.6 (the default), strong 0.85, tripod 1).
--crop is how much of the picture is cut off to hide the moving edges:
auto (the default, the least that hides them) or a fraction up to 0.3. The
engine keeps the measured camera path, so a second run on the same clip is
fast.
Changes a stabilised clip: --enabled true|false, --strength, --crop.
The clip must have a stabilisation from stabilise apply.
Finds the beats in the sound of a clip: a music clip, or the linked sound of a
video clip. The marks go on the clip that plays the sound. The result gives
the tempo (bpm) and the beat times.
Cuts video clips on the beats that beats detect found. --every N keeps
every N-th beat (default 1). Without clips, it cuts every clip on the video
lanes. One undo step.
Moves each cut between the clips to the nearest beat. It rolls the cut: the
clip before the cut gets longer by the time that the clip after it loses, so
nothing else moves. --tolerance TIME is the farthest a cut can move
(default: half a beat at the slowest tempo, or 250 ms). Without clips, it
uses every clip on the video lanes. One undo step.
chukcut-cli beats detect reel.chukcut 1:0
chukcut-cli beats cut reel.chukcut 0:0 --every 2Finds the subject of each clip and moves a window of the canvas's shape with
it, as position keyframes. The subject is the faces that YuNet finds. On a
frame without a face, the subject is the people that the person detector
finds (the head and the shoulders of each person). On a frame without both,
the subject comes from the saliency of the picture. --ratio W:H (for example 9:16, 1:1, 4:5)
also changes the project to that shape, in the same undo step. Without clips,
the CLI uses each clip that fills its frame on a visible video lane.
chukcut-cli reframe reel.chukcut --ratio 9:16Shows what a clip has from the commands above: the scene changes and the beats in timeline seconds, the tempo, and the stabilisation. It does not change the project.
These commands use the cloud accounts that you set up in the app (Settings,
Accounts). catalog accounts lists them. The CLI cannot add an account or a
key. Each command takes --account ID. Without it, the CLI uses the first
account that can do the job. When there is no such account, the command
fails with exit code 1 and changes nothing.
Translates the first caption lane into the language LANG (ISO 639-1, for
example de). The translation goes on a new caption lane, a little above the
original. --from LANG gives the captions' language (default: detected).
--model is the chat model for an OpenAI-compatible account. Needs a DeepL
or an OpenAI-compatible account. One undo step.
Speaks the text with a cloud voice (ElevenLabs or OpenAI-compatible) and
imports the sound file into the project. --at TIME also puts it on an audio
lane at that time. --model, --speed (1 is normal) and --instructions
(OpenAI: tone, accent, emotion in plain words) change the voice. The file goes
to ~/.local/share/chukcut/generated, with a record of its source and
licence.
chukcut-cli cloud tts reel.chukcut "Three tips for better sleep" --voice nova --at 0Lists the kinds of stock (video, photo, sound) that the account's
library has.
Searches a stock library (Pexels, Pixabay or Freesound). --kind video|photo|sound (default video), --page (from 1), --per-page
(default 24), --non-commercial (also show sounds that do not allow
commercial use). The result lists each hit's id, title, creator, size,
licence and credit line. The CLI keeps search results for one day. It does not
change the project.
Makes a sound effect from a description, or music with --music, with an
account that can (ElevenLabs), and imports it. --seconds, --looping
(sound effects), --instrumental (music), --at TIME to put it on the
timeline.
Runs a fal.ai action (catalog fal_actions) on the file of a video clip.
Without --confirm, the CLI only asks fal for the price and shows it. With
--confirm, it uploads the file, runs the action (this costs money on the
account), imports the result and puts it at the clip's start on a lane of its
own. The clip does not change.
Shows what the licences of the media on the timeline ask for: the items that
need a credit, the items that are not for commercial use, and the credits
text. --write VIDEO writes VIDEO.credits.txt next to an exported video,
as the app does after an export. Changes nothing in the project.
Downloads one result of a search and imports it into the project. Give the
same query, --kind and --page as the search; the CLI finds the result by
its --id. --at TIME also puts the file on the timeline at that time.
chukcut-cli cloud stock-search reel.chukcut "ocean waves" --kind video --json | jq '.data.hits[].id'
chukcut-cli cloud stock-download reel.chukcut "ocean waves" --kind video --id 1234567 --at 4Transcribes the timeline's speech and puts the captions on the caption lane, with word times for the karaoke highlight. It uses the transcriber that the app's caption panel uses, unless you give options:
| Option | |
|---|---|
--backend cloud|local |
an OpenAI-compatible account, or whisper.cpp on this machine |
--account ID |
the cloud account (add it in the app: Settings, Accounts) |
--model NAME |
the cloud model |
--local-model |
tiny, base, small, medium or large_v3_turbo; downloaded on first use |
--language CODE |
ISO 639-1; detected when not given |
--words N |
word captions, at most N words on screen; without it, sentence captions |
--keep |
keep the captions that are there (default: replace them) |
--emoji |
add one emoji to each caption |
--preset |
classic, karaoke, yellow, boxed or big |
chukcut-cli captions transcribe reel.chukcut --backend local --words 2 --preset karaokeReads an .srt or .vtt file. Same --keep, --emoji, --preset.
Writes the captions. The format comes from the file extension when you do not give it.
Changes every caption, or one with --clip. --preset first, then
--font, --size, --color, --highlight COLOUR|none (karaoke word
colour), --bold, --italic, --align, --stroke-width, --stroke-color,
--background COLOUR|none, --position top|middle|bottom|Y.
Puts one caption on the caption lane, next to the captions that are there, in their style.
Changes the words of one caption.
Cuts a caption in two at a time, or joins two neighbouring captions into one.
Deletes every caption.
Groups the captions again from their words: word captions with at most N
words on screen, or sentence captions without --words.
Finds the pauses in a clip's sound. It does not change the project. The result
lists each cut in timeline time and in source time, and the total time that
silence remove would take out.
| Option | Default | |
|---|---|---|
--threshold DB |
from the recording | quieter than this is a pause (dBFS) |
--min-silence TIME |
0.5 s | shorter pauses stay |
--padding TIME |
0.12 s | kept on the speech side of each cut |
--voice |
also cut parts without a voice (breaths, room tone) |
Cuts the pauses from the clip and its linked sound, and closes the gaps. One
undo step. The other lanes (captions, music, titles) move with the cuts, so
captions stay on their words. --no-sync stops this. --fillers also cuts
filler words ("um", "uh") that it finds in the clip's captions; transcribe
first. --language (default en) selects the filler word list.
chukcut-cli silence remove reel.chukcut 0:0 --threshold -38 --min-silence 0.35Brings speech to a loudness. --target LUFS (default -14, from -40 to -5).
--clip for one clip; without it, every clip that makes sound. The gain is
capped so that peaks do not clip. --off removes the normalisation. For the
whole mix, use export --loudness.
Reduces background noise (RNNoise). --strength from 0 to 1 (default 1).
--off turns it off. The first run renders a clean copy of the sound into the
cache.
Separates a clip's speech from music and noise with HTDemucs (MIT, 316 MB,
in the ML worker): --keep voice (default) keeps the speech,
--keep background keeps everything but the voice (music without the
singer). --strength is how much of the rest goes (default 1). The setting
is one undo step; the command then renders the isolated sound into the
cache and waits (about 11 s for a minute of sound on an RTX 3060, 36 s on
the CPU), unless --no-render. Until it is rendered the clip plays as it
was; an export renders what is missing first. denoise works on what
isolation kept. Running it again with the same setting renders what is
missing.
Measures EBU R128 loudness: integrated LUFS, loudness range and true peak. For one clip, or for the whole mix as the export would make it.
Adds an audio effect to the clip's sound (a video clip's linked audio clip
when it has one): eq3 (low, mid, mid_freq, high), eq5 (five bands of
frequency, gain and width), compressor, reverb, delay (an echo),
pitch (semitones, keeping or moving the formants), or a voice preset.
catalog audio lists every parameter with its range and default. Effects run
in stack order; the clip's speed change comes first.
Changes an effect, named by its index in the clip's audio stack, its kind or its id: parameters, on or off, or its position in the stack.
Takes an effect off; lists the stack with every parameter's value, the pitch switch and any ducking.
The voice changer: deep, chipmunk, robot, telephone or megaphone.
A clip has one voice at a time; a new one replaces the old one in place.
"Change audio pitch". Every speed change keeps the pitch by default (a
time stretch). With --follow-speed the pitch moves with the speed, like a
tape; without it, it is kept again. Speed curves follow the same switch.
Turns a music clip down wherever someone speaks on another lane (default
12 dB, 250ms attack ending where speech starts, 500ms release). Speech is
found by level and by RNNoise's voice detector, so a sound effect does not
duck the music. The result is volume keyframes, multiplied into any fades the
clip has, in one undo step. Ducking again starts from the clip's own volume;
--off gives it back.
Records a voiceover from the default input device for --duration (after an
optional count-in, which is not kept) and puts it on a new audio lane at
--at. The file is saved next to the project in <project name> Media/.
Renders the timeline to a file. The command waits until the file is complete and shows progress on stderr.
| Option | |
|---|---|
--preset ID |
a preset from presets (see below), or custom (the project's canvas and frame rate; the default) |
--hardware ID |
a hardware encoder from catalog hardware (nvenc_h264, vaapi_h265, …), auto for the first one that works, or software |
--width, --height, --fps |
override the preset |
--codec |
h264, h265, vp9, av1, prores, gif |
--crf N or --bitrate BPS |
quality |
--container |
mp4, mov, mkv, webm, gif; sound only: m4a, mp3, wav. The file extension follows the container |
--audio-codec |
aac, opus, mp3, pcm, none |
--audio-bitrate BPS |
|
--no-audio |
|
--loudness LUFS |
bring the mix to this loudness, true peak at -1 dBTP; overrides the preset's target |
--no-loudness |
keep the mix as edited, also when the preset has a target |
--from TIME, --to TIME |
export only this range |
--sidecar srt|vtt |
also write the captions next to the video |
--color-matrix auto|bt709|bt601 |
the YUV matrix the picture is converted with and tagged as. auto (the default) is BT.709 when the long side is over 1024 or the short side over 576, else BT.601 |
--color-range limited|full |
limited (16–235, the default) or full (0–255) range, tagged |
--ten-bit |
10 bits a sample: HEVC Main 10 with --codec h265, 10-bit AV1 with --codec av1; refused for the other codecs. Works on the hardware encoders too (nvenc_h265, vaapi_h265, …) |
The built-in presets:
| Preset | Size | Rate | Picture | Sound | Loudness |
|---|---|---|---|---|---|
tiktok |
1080p, canvas shape | 30 | H.264 CRF 20 | AAC 192k | -14 LUFS |
instagram_reels |
1080p, canvas shape | 30 | H.264 CRF 21 | AAC 192k | -14 LUFS |
youtube_shorts |
1080p, canvas shape | 30 | H.264 CRF 20 | AAC 256k | -14 LUFS |
instagram_square |
1080×1080 | 30 | H.264 CRF 21 | AAC 192k | -14 LUFS |
x_twitter |
1080p, canvas shape | 30 | H.264 8 Mbit/s | AAC 128k | -14 LUFS |
youtube_1080p |
1080p, canvas shape | project | H.264 CRF 20 | AAC 384k | -14 LUFS |
youtube_4k |
2160p, canvas shape | project | H.265 CRF 22 | AAC 384k | -14 LUFS |
master_prores |
canvas | project | ProRes 422 HQ 10-bit, .mov | PCM 16-bit | as edited |
master_h264 |
canvas | project | H.264 CRF 14 | AAC 320k | as edited |
master_hevc |
canvas | project | H.265 CRF 16 | AAC 320k | as edited |
audio_aac |
— | — | — | AAC 256k .m4a | -16 LUFS |
audio_mp3 |
— | — | — | MP3 320k | -16 LUFS |
audio_wav |
— | — | — | PCM 16-bit .wav | as edited |
gif |
480p, canvas shape | 15 | GIF, 252 colours | — | — |
"1080p, canvas shape" means: the shorter side is 1080 and the aspect ratio
is the canvas's. A 9:16 canvas gives 1080×1920, a 16:9 canvas 1920×1080. The
composition is never boxed into another shape. When the canvas does not
have the shape that the platform shows full screen, or the timeline is
longer than the platform accepts, the result has a warnings list. The old
id vertical_1080x1920 still works and means tiktok.
The software encoder is the default. A hardware encoder is a choice, because the engine trial-encodes each one before it uses it. ProRes, GIF and sound only always use the software encoder.
Every video export is SDR, tagged with its matrix, its range and BT.709 primaries and transfer (decision 0034). HDR sources are tone-mapped to SDR on the way in; there is no HDR export.
The result gives the path, the size in bytes, the frame count, the time it took, the encode speed, the output size, the loudness target and the warnings.
chukcut-cli export reel.chukcut out/reel.mp4 --preset tiktok \
--hardware auto --sidecar srt --json
chukcut-cli export reel.chukcut out/voice.mp3 --preset audio_mp3Lists every preset as it fits this project: the size and frame rate it
exports at on this canvas, the container, the loudness target, the warnings
and an instant size estimate. Your own presets come last, with user: true.
Saves export settings as a preset of your own. Start from a preset and add
overrides; every export option except the output is allowed. The preset
keeps the resolution class, so a "1080p" preset also exports 1080p on a
canvas of another shape. The id is user_ and the name in lower case.
Saving the same name again replaces the preset. Presets are stored in
<config>/chukcut/export-presets.json; the app and the CLI share them.
chukcut-cli preset save reel.chukcut "Reel HQ" --preset instagram_reels --crf 18
chukcut-cli export reel.chukcut out/reel.mp4 --preset user_reel_hqDeletes one of your own presets. A built-in preset cannot be deleted.
Tells what an export will produce and how big it will be, without writing
it. The size of a CRF export depends on the picture. Without --sample,
the size of a CRF export is a rough guess from a table
(estimate.method: "table"). With --sample, the engine encodes three
two-second windows of the timeline (the whole timeline when it is 8 s or
shorter) with the real settings and measures the size
(method: "sampled"). A bitrate export and a sound-only export are
calculated, not sampled (method: "bitrate", "exact" for WAV). The
estimate includes the audio and the container overhead. In the tests the
sampled and calculated estimates are within 2 % of the real files.
Queues several exports and runs them one after another. The command waits until all files are written. Progress shows the item and its percentage.
--presets ID,ID,…(a list, or the flag repeated) exports this project once per preset, to<out-dir>/<project>-<preset>.<ext>. The other export options (for example--from/--to,--hardware) apply to each of these. Without--out-dir, the files go next to the project.--preset IDalone queues one export.--jobs FILE(or-for stdin) is a JSON list of jobs. A job is an object withoutputand the export options (preset,from,to,crf,container, …). A job can name another project file inprojectand a name for the progress lines inlabel.
Every job is checked before the first one starts, so a wrong preset name in the third job stops the command at once. When an export fails, the others still run; then the command fails with exit code 5 and names the failed jobs.
chukcut-cli export-queue reel.chukcut --presets tiktok,youtube_shorts,audio_mp3 \
--out-dir out/
echo '[{"output":"out/intro.mp4","preset":"x_twitter","from":0,"to":10},
{"output":"out/other.mp4","project":"other.chukcut","preset":"youtube_1080p"}]' \
| chukcut-cli export-queue reel.chukcut --jobs -In the app, the export dialog has the same queue: "Add to queue" puts the export in the queue and the queue keeps running when the dialog is closed.
Writes the frame at a time as a PNG at the full canvas size. It uses the export compositor, so it shows the same pixels as the export.
Not tied to a project. status says what runs models ("CUDA 13 on the GPU
with chukcut's CUDA libraries", "the CPU (CUDA: …)"), which GPU and NVIDIA
driver the machine has, which GPU bundle fits it and what the baked mattes
take on disk; with --probe it starts the ML worker to find out what really
loads (it lists the CUDA libraries the worker opened, by path). models,
runtimes and bundles list what can be installed, with sizes and
licences. install ITEM, remove ITEM, bench MODEL [--size WxH] [--iterations N].
An ITEM is a model (yunet, vittrack, rvm, birefnet-lite,
mobilesam, rife, lama, realesr-general-x4v3, facemesh,
htdemucs-vocals, rtmpose-m, yolox-tiny-human), a runtime pack (runtime:cpu, runtime:cuda13,
runtime:cudnn9-cu12, …) or a GPU bundle: gpu installs the one for
this machine's NVIDIA driver, gpu:nvidia-cu13 (driver 580 or newer,
1.3 GB) or gpu:nvidia-cu12 (driver 525 or newer, 1.9 GB) a named one. A
bundle is ONNX Runtime's CUDA build plus every CUDA library its provider
needs (the CUDA runtime, cuBLAS, cuRAND, NVRTC and cuDNN 9), from NVIDIA's
own wheels on PyPI, pinned by SHA-256; the worker loads them by path, so
nothing has to be on LD_LIBRARY_PATH and an old system CUDA does not get in
the way. CHUKCUT_ML_RUNTIME (cpu, cuda12, cuda13) forces one
installed build; CHUKCUT_CUDA_LIB_DIRS (colon-separated) names directories
with CUDA libraries to prefer over the bundle's; CHUKCUT_ORT_DYLIB names
another ONNX Runtime build (an OpenVINO one for Intel GPUs). Also an MCP
tool, ml.
Fast acceleration (decision 0031). ml acceleration fast|standard sets
Settings › AI acceleration › "Fast (fp16/TensorRT)"; ml install tensorrt
(or tensorrt:tensorrt-cu13, tensorrt:tensorrt-cu12) installs the
TensorRT add-on for the installed GPU bundle (3.7–4.3 GB download). In Fast
mode RIFE, Real-ESRGAN, LaMa and BiRefNet run on TensorRT at the precision
measured for each; the first job of a model at a new size builds its engine
once (30 s to ~5 min) and caches it. ml status prints a table: each
model, what it runs on, its precision and the engines built so far with
their build times. ml bench MODEL --accel standard|fast times one mode
(default: the configured one) and --compare adds how far its output is
from the standard fp32 session's (PSNR, max difference, IoU for mattes).
ml bench with no model times the heavy models at the sizes the features
use, in both modes, and prints the speed-ups and the quality of Fast.
CHUKCUT_ML_ACCELERATION (standard, fast) overrides the setting for
one process.
chukcut-cli ml status --probe
chukcut-cli ml install gpu
chukcut-cli ml bench rvm --size 540x960
chukcut-cli ml bench mobilesam --size 960x540
chukcut-cli ml bench lama --size 512x512
chukcut-cli ml bench realesr-general-x4v3 --size 1280x720
chukcut-cli ml bench rtmpose-m --size 1280x720
chukcut-cli ml install tensorrt
chukcut-cli ml bench rife --size 1920x1080 --accel fast --compare
chukcut-cli ml benchrtmpose-m and yolox-tiny-human come as zip archives. The archive must
have the SHA-256 in the registry. Then the CLI copies one file out of the
archive (the model, at the path that the registry gives). The file must have
the size and the SHA-256 in the registry. The CLI writes no other file from
the archive, and it deletes the archive after.
These are operations for a batch and for the MCP server. A one-shot command
starts with an empty history, so undo has nothing to undo there. The undo
history is not stored in the project file (the same as in the app).
batch PROJECT FILE runs a list of operations against one open project. Use
- for stdin. The operations share one undo history, so undo and redo work
between them. The batch is all or nothing: the CLI saves once, at the end, and
only when every operation succeeded. When operation 3 fails, the error says
operation 3 (name): … and the file does not change.
The file is a JSON list, or an object with an ops list. Each operation is an
object with op and the same arguments as the command, in snake_case. Lists
like --set can be an object:
[
{"op": "new", "width": 1080, "height": 1920},
{"op": "import", "files": ["take1.mp4", "music.mp3"], "append": true},
{"op": "silence_remove", "clip": "0:0", "min_silence": "350ms"},
{"op": "split", "at": "4.5s"},
{"op": "grade", "clip": "0:1", "set": {"exposure": 0.3, "saturation": 1.1}},
{"op": "title_add", "text": "Day 1", "at": 0.5, "color": "#ffcc00"},
{"op": "undo"},
{"op": "redo"},
{"op": "transition_add", "clip": "0:1", "kind": "dissolve", "duration": 0.4},
{"op": "export", "output": "out/reel.mp4", "hardware": "auto"}
]When the first operation is new, the batch makes the project.
The operation names are the MCP tool names: info, validate, configure,
import, undo, redo, append, place, split, delete, move,
trim, clip_set, grade, effect_add, effect_set, effect_remove,
animate, animate_text, zoom, keyframe, title_add, title_set,
transition_add, transition_remove, track, track_set, mask, chroma_key,
remove_background, select_object, apply_to, blend,
auto_adjust, colour_match, grade_preset_save, grade_preset_apply,
grade_presets, isolate_voice, face_landmarks, retouch,
follow_face, body_landmarks, follow_body,
frame_blend, smooth_slow_mo, speed_effect, captions_transcribe,
captions_import, captions_export, captions_style, captions_list,
silence_detect, silence_remove, normalize, denoise, loudness,
marker_add, marker_set, marker_remove, marker_list, crop, curve,
freeze, speed_curve, layout_pip, layout_split, title_style,
title_template, title_position, title_duplicate, scenes_detect,
scenes_split, scenes_clear, stabilise, stabilise_set,
stabilise_remove, beats_detect, beats_clear, beats_cut, beats_snap,
reframe, analysis, translate_captions, tts, stock_kinds,
stock_search, stock_download, audio_effect_add, audio_effect_set,
audio_effect_remove, audio_effects, voice, audio_pitch, duck,
record, export, presets, preset_save,
preset_remove, estimate, export_queue, render_frame. The arguments
are the command's options and positional arguments without the project.
In export_queue, the jobs are a jobs list rather than a file. chukcut-cli mcp lists each one's
JSON Schema (see below).
chukcut-cli mcp is an MCP server on stdio (newline-delimited JSON-RPC 2.0).
It supports the protocol versions 2025-11-25, 2025-06-18, 2025-03-26 and
2024-11-05. When a client asks for a different version, the server answers
with 2025-11-25.
claude mcp add chukcut -- chukcut-cli mcpGive the full path when chukcut-cli is not on your PATH:
claude mcp add chukcut -- /home/you/.local/bin/chukcut-cli mcp--scope user makes it available in all your projects. Other MCP clients use
the same command: the program chukcut-cli with the argument mcp.
Each operation above is a tool with the same name and a JSON Schema made from
the same argument struct that the CLI parses. A tool schema cannot be
different from what the tool accepts. Each tool (except catalog) also takes
project, the absolute path of the .chukcut file; template_list and
template_delete do not.
The server adds four tools:
| Tool | |
|---|---|
new_project |
makes a project file (width, height, fps, name, force) |
view_frame |
renders the frame at at and returns it as a PNG image in the result; writes no file |
batch |
runs ops (a list as in a batch file) all or nothing |
catalog |
lists effects, transitions and so on (kind); needs no project |
Tool results have a text block with {"message": …, "data": …}. For clients
on 2025-06-18 or later, the same object is also in structuredContent. A
refused edit is a tool result with isError: true and the engine's message;
an unknown tool or a malformed request is a JSON-RPC error.
Read-only tools have readOnlyHint: info, template_list,
template_slots, validate, captions_list,
silence_detect, loudness, catalog, view_frame, marker_list,
analysis, stock_kinds, stock_search, presets, estimate,
face_landmarks and body_landmarks (which write only the landmark
cache).
Tools that send data to a service outside this machine have
openWorldHint: captions_transcribe, translate_captions, tts,
stock_kinds, stock_search, stock_download, sound, fal, sticker,
music, sfx, title_font, catalog (the library and voices kinds),
and ml, remove_background, select_object, apply_to, frame_blend,
smooth_slow_mo, speed_effect, remove_object, enhance_quality, isolate_voice,
face_landmarks, retouch, follow_face, body_landmarks and
follow_body, which download a model or ONNX Runtime on first use (they
send nothing about the project).
| URI | |
|---|---|
chukcut://project?path=/abs/path.chukcut |
the info summary, JSON |
chukcut://frame?path=/abs/path.chukcut&at=2.5 |
the frame at at, PNG |
resources/list lists the projects that the connection opened.
resources/templates/list gives the two templates. Percent-encode the path.
- The server keeps each project open for the life of the connection.
undoandredowork across tool calls. - Each successful edit is saved to the file at once. When an agent stops in the middle of a task, the project is consistent.
- When an edit fails, the server discards what it changed in memory. The file keeps its last good state.
- When the file changes on disk (for example, you edit it in the app), the server reads it again before the next call. The undo history then starts again.
- The server does one request at a time. A long export blocks the connection
until it is done. When the request has a
progressToken, the server sendsnotifications/progressduring the export, the transcription, the tracking, the sound analysis, the picture analysis (scenes, stabilise, reframe), the beat detection and a stock download.
What a client sends, one line each:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"me","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"new_project","arguments":{"project":"/home/me/reel.chukcut"}}}
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"import","arguments":{"project":"/home/me/reel.chukcut","files":["/home/me/take1.mp4"],"append":true}}}
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"split","arguments":{"project":"/home/me/reel.chukcut","at":2}}}
{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"view_frame","arguments":{"project":"/home/me/reel.chukcut","at":2.5}}}#!/usr/bin/env bash
set -euo pipefail
p=reel.chukcut
chukcut-cli new "$p" --force
chukcut-cli import "$p" take.mp4 --append
chukcut-cli denoise "$p" 0:0
chukcut-cli captions transcribe "$p" --backend local --words 2 --preset karaoke
chukcut-cli silence remove "$p" 0:0 --fillers
chukcut-cli zoom "$p" 0:0 --auto --amount 1.12
chukcut-cli normalize "$p" --target -14
chukcut-cli export "$p" reel.mp4 --preset vertical_1080x1920 --hardware auto --sidecar srtTranscribe before silence remove --fillers: filler words come from the
captions. silence remove keeps the captions on their words.
id=$(chukcut-cli --json split reel.chukcut --at 4 --clip 0:0 | jq -r '.data.created[0].id')
chukcut-cli grade reel.chukcut "$id" --set exposure=-0.2chukcut-cli --json export reel.chukcut out.mp4 | jq '.data | {path, frames, bytes}'
ffprobe -v error -count_frames -show_entries stream=nb_read_frames out.mp4- Export and render need a GPU. The compositor runs on Vulkan. On a machine
without a GPU, install Mesa's lavapipe (software Vulkan). Without any
Vulkan driver,
export,render-frameandview_framefail with exit code 5. - No cancel. Ctrl+C stops the process; an export that stops early leaves
a partial file. The same is true for
export-queue: the queue lives in the process, so the exports not yet run are not run. - Undo history lives only in one session (one command, one batch, one MCP connection). The project file does not store it.
- Cloud features need an account that you set up in the app. The CLI cannot add accounts or keys. Without an account, a cloud command fails with exit code 1.
- The stock commands take a project (as every operation does), but they
do not change it, except
cloud stock-download.
crates/cli/src/ops/holds one argument struct per operation. The struct is the CLI options (clap), the batch and tool arguments (serde) and the MCP schema (schemars). To add an operation, write the struct and itsrun, then add it to theoperations!list inops/mod.rsand give it a subcommand: a variant inmain.rs, or in a subcommand enum of itsops/file thatmain.rsflattens in (ops/clip.rs,ops/library.rsand others do this, so that a new group touchesmain.rsin two lines).- Every command-layer function is reachable.
tests/reachability.rsreads eachmodules/*/commands.rsand fails when apub fnis not called fromcrates/cli/src, unless itsALLOWLISTgives the reason (live preview, jobs inside one process, preview tiles, account keys, ...). The same test checks that every operation is inoperations!(so batch and MCP have it) and has a subcommand. A new engine command therefore needs an operation, or an allowlist line that says why not. - An operation builds its edit with the engine's command functions
(
modules/*/commands.rs) and the gesture builders inmodules/timeline/gesture.rs. It does not change aProjectdirectly. - Tests:
cargo test -p chukcut-cli.tests/flow.rsruns the binary on generated media and checks the export with ffprobe.tests/mcp.rsdrives a full MCP session over a pipe.tests/coverage.rschecks the later operations (markers to cloud) in the saved project file. Its cloud test uses an OpenAI-compatible stand-in server on 127.0.0.1, so no request leaves the machine.