Command line
Every command of BetterEdits cli with its options, grouped, with one example each.
Running commands
The command line is the app's own binary. Run it from the workspace folder.
/Applications/BetterEdits.app/Contents/MacOS/BetterEdits cli <command> [value…] [--option value…]
- Commands talk to the running app over a Unix socket at
~/Library/Application Support/BetterEdits/cli.sock. If the app is not running the command launches it in the background and waits up to 20 seconds. - Positional values fill a command's required options in order, then its listed positionals:
clip-split v1:1 2isclip-split --clip v1:1 --at 2. - A bare
--flagmeans true.--key=valueworks too. Numbers andtrue/falseare typed; everything else is text. - Relative paths resolve from the folder you run in.
helplists every command;help <command>or<command> --helpprints its options.- A failing command prints why and exits 1. Exit 2 means the app could not be reached.
- Every command is an undo step in the app. With a workspace open but no video, editing commands are refused until
project-openorproject-new.
BETTEREDITS_NO_CLI=1 in the app's environment keeps the socket closed.
Refs and times
| What | How to write it |
|---|---|
| Tracks | v1, v2 (video, top first), a1 (audio), t1 (text), s1 (subtitles); a track's name; or its 8-character id |
| Clips | v1:2 is the second clip on v1 in time order; or the clip's 8-character id from timeline |
| Subtitle bars | s1:3 or the bar id |
| Assets | The file's display name (its filename without extension), its id, or its path |
| Times | Seconds (4.5), 1:02.5, end, playhead |
Positional refs change after edits. Ids last while the app runs and follow moves made in the app, but they are not in the project files: after an edit on disk they follow positions, and reopening a project mints new ones. Re-read timeline after any edit.
Read
| Command | Options | Does |
|---|---|---|
status | The open project: name, path, files, duration, playhead, selection, tracks with clip counts; problem when the files on disk were refused | |
timeline | --track | Every track with every clip (ref, id, start, end, source in and out, text and position) or every subtitle bar |
media | The media files the project uses, with copied: true for files copied into media/ | |
probe | --path (required) | A file on disk: kind, duration, size, frame rate, sound, HDR |
favorites | The text favorites and caption styles with font, size and colors | |
guide | The editing guide as text | |
check | [project] | Lint a project's files through the app: every problem and warning at once; for the open project it adds what the app refused |
lint | [project], --json | The same without the app: reads project.json, timeline.json and styles.json, checks every clip against its file's real length, and warns about unused media or looks, text past the end or outside the safe area, very short or long bars, empty tracks and standing placeholders. Exit 1 on errors |
sync | --timeout | After writing a file: wait until the app has taken it in or refused it, and say which |
levels | --path (required), --every, --silence, --min_silence | A file's loudness over time (RMS in dBFS per step) and its silences, from the sound alone |
help | [command] | The command list, or one command's options |
be probe ~/Footage/talk.mov
be timeline --track v1
be stands for the full command above. There is no be on your Mac.
Workspace and projects
| Command | Options | Does |
|---|---|---|
workspace | [path], --about | Show the workspace, or set one up at a path and switch to it; --about says what gets made there and sets the canvas new videos start with |
media-folders | --add, --remove, --consolidate, --force | List the media folders, add one, or remove one. Removing a folder videos still use needs --consolidate (copy the files into the videos first) or --force |
projects | The projects in the workspace, newest first | |
project-new | [name], --brief, --canvas, --structure, --force | Start a project in its own folder, with a brief, a canvas (9:16, 16:9, 1:1, 4:5) and a built-in structure. Without a workspace, an unsaved Untitled project; --force discards unsaved changes |
project-open | --project (required), --force | Open a project by name, or a project folder, project.json or .be path |
project-save | [path], --force | Save now (the app saves by itself anyway); while the files on disk stand refused, --force replaces them with the app's copy. With a path, write a .be copy there |
ratio | [to] | Show or change the canvas: 9:16, 16:9, 1:1 or 4:5 |
be project-new "Hook v2"
be media-folders --remove ~/Footage/June --consolidate
Tracks
| Command | Options | Does |
|---|---|---|
track-add | --kind (required: video, audio, text), --name, --magnetic, --top | Add a track. Video goes right above the audio tracks, or on top with --top; audio at the bottom; text on top |
track-set | --track (required), --name, --magnetic, --locked, --hidden, --opacity (video, 0 to 1), --muted, --solo, --volume (0 to 1.5), --ducks (audio) | Change a track |
track-remove | --track (required) | Delete a track and everything on it |
be track-set v1 --locked
Clips
| Command | Options | Does |
|---|---|---|
media-import | --paths (required, several bare values work) | Register files with the project without placing them; files outside the video and its libraries are copied into the video |
media-relink | asset, path | Point an asset (a missing one, say) at another file; every clip of it follows, cut to the file's length if shorter |
clip-add | --track (required), --asset, --path, --at, --in, --out, --duration | Put a piece of a file on a video or audio track. Defaults: the whole file (photos 3 s), appended at the end of the track |
placeholder-add | --name (required), --track, --duration (default 3), --at | Add a named stand-in: a black plate on video, silence on audio |
clip-replace | --clip (required), --asset, --path, --with, --fill | Swap what is behind a clip or placeholder, keeping its spot and length. --with moves another clip in; --fill puts a placeholder over the rest when the source is shorter |
clip-slip | --clip (required), [to], --by | Slide which part of the file the clip plays. --to is the new source in point; --by shifts it |
clip-split | --clip, --at (both required) | Cut a clip in two at a timeline time |
clip-trim | --clip (required), --start, --end, --in, --out | Move a clip's edges. start and end are timeline times; in and out are source times |
clip-move | --clip, --to (both required), --track | Move a clip to a time, optionally onto another track of the same kind |
clip-remove | --clip (required) | Delete a clip |
clip-set | --clip (required), --volume (0 to 1.5), --scale, --offsetX, --offsetY, --cropLeft, --cropRight, --cropTop, --cropBottom (0 to 0.45), --name | Adjust level, picture scale, offset, crop, or a placeholder's name |
clip-duplicate | --clip (required) | Copy a clip, or a subtitle bar, right after itself |
be clip-add v1 --path ~/Footage/talk.mov --in 12.4 --out 18.9
be clip-split v1:1 2
be clip-replace v1:2 --with v1:5 --fill
Text
| Command | Options | Does |
|---|---|---|
text-add | --text (required), --at (default playhead), --duration (default 3), --track, --favorite, --font, --size (8 to 240), --color (#RRGGBB), --uppercase, --x, --y (0 to 1) | Put text on screen for a stretch of time, wearing a favorite with overrides |
text-set | --clip (required), --text, --duration, --favorite, --font, --size, --color, --uppercase, --x, --y | Change a text's words, look or position |
be text-add "Stop doing this" --at 0 --duration 2.5 --favorite Strong --y 0.3
Captions
| Command | Options | Does |
|---|---|---|
transcript | --track | The words spoken on a track with start and end times, from its clips' analysed footage; names the files that have not been analysed. Adds nothing to the project |
captions-generate | [source], --replace | Make a subtitles track with bars from the transcript of a track's analysed footage, or refill one with --replace s1 (every bar replaced). The bars are linked to nothing and do not follow later cuts |
captions | --track | The bars of a subtitles track |
caption-edit | --bar (required), --action (set, merge, split, remove), --text, --start, --end | Fix one bar |
captions-style | --track, --style, --position (top, center, bottom), --offset (bottom only, 0.02 to 0.5) | Give a subtitles track a caption style and a position |
be caption-edit s1:3 --text "Stop doing this"
be captions-style --style "Bold" --position bottom --offset 0.2
Analysis
Claude cannot watch video. analyze reads a file once through the BetterEdits analysis service and writes <file>.analyzemedia next to it: every spoken word with its timing, speakers, on-screen text, scenes and cuts, silences, music. transcript and captions-generate read it, and so does Claude, whole. Analysis is part of Pro (a 7-day free trial, then $19 a month with $22 of credit every month; video costs 20¢ a minute, speech 6¢). The Mac signs in once through login; the credential lives in the app's own settings, never in a workspace. Claude Code runs all of this for you; see Claude Code.
| Command | Options | Does |
|---|---|---|
analyze | files (one or more paths), --type (video/footage, video/edit, audio/speech, audio/music; default by kind), --force | Upload each file, wait, write <file>.analyzemedia next to it, and report the words found, the charge and the balance left. A file that already has one is skipped unless --force. Signed out it fails with "Not signed in"; without Pro with the link to start it; without enough credit with the amount needed and the buy link |
login | Signs this Mac in: opens the dashboard in the browser, waits for the approval, keeps the credential in the app's settings | |
logout | Signs this Mac out | |
account | Who is signed in, the plan (Pro, trial, free), the credit as dollars and minutes of video, and the dashboard links |
be login
be analyze ~/Footage/talk.mov
be account
Look
| Command | Options | Does |
|---|---|---|
reveal | what (a clip ref, asset or path) | Show a file in the Sources sidebar, folders opened, tile lit, as Show in Sources does |
preview | [path], --off | Show a media file in the main player, as a click on it in the Sources sidebar does; --off brings the timeline back |
frame | --at (required), --width (default 360, max 1080), --out | The picture at a time, with text and captions drawn on, as a PNG |
contact-sheet | --out, --path, --clips, --every, --times (list), --start, --end, --columns (default 4), --width (default 240) | One PNG of many frames, each labelled. Default: 12 frames over the piece; --clips one frame per clip with its ref; --path a source file's frames, to look before cutting |
Without --out, PNGs go to cache/frames/ in the workspace, named after the command and the time. The command prints the path.
be contact-sheet --clips
be contact-sheet --path ~/Footage/talk.mov --every 2
be levels ~/Footage/talk.mov
be frame 3.2 --out cache/frames/hook.png
Drive the app
| Command | Options | Does |
|---|---|---|
seek | --at (required), --play | Move the playhead, optionally start playing |
select | --target (required) | Select a clip or bar, or none to clear |
app-show | Bring the window to the front | |
undo | Undo the last change, yours or the user's | |
redo | Redo the last undone change | |
export | [path], --preview, --height, --start, --end | Render an MP4 with text and captions burned in. Default path: projects/<Name>/exports/<Name>-<date>.mp4. --preview is a quick 540p standard-range file; otherwise the footage's own size, HDR kept. --height is the short side, as the export sheet counts (1080, 1440, 2160) |
be select v1:2
be export --preview
Templates
| Command | Options | Does |
|---|---|---|
template | --out | The open project as a template: the first video and audio tracks' clips as named segments, every text with its look |
template-import | --file (required), [name], --here | Start a project from a template file, or add it to the open project with --here |
be template --out hook.json
be template-import hook.json "Hook v3"