EditAI 00:00:00:00 GitHub
00:00:00 Cold open

Talkto yourtimeline

EditAI is an AI harness for video editing. Ask for the cut, the motion graphic, the filter or the noise gate. An agent makes the edit on your real timeline through 16 MCP tools, and stops for your approval before anything destructive.

⌘⏎
V1
A1
T1
Waiting for an instruction 24.0s

Real behaviour, real numbers: find_silences then ripple_delete across every track, 24.0s down to 21.1s, which is exactly the 2.9 seconds of dead air. Nothing is cut until you approve it, and every edit undoes.

00:00:14 The handoff

Connect the MCP.
The agent takes the room.

Point your client at EditAI's MCP server and an agent comes up inside a sandbox on TrueForge, TrueFoundry's open-source agent harness. From there it drives the edit at whichever layer the job needs.

Layer one

Your editing UI

Bring your own front end. The timeline is exposed as tools, not as a prompt describing a timeline, so any MCP client can drive it.

any MCP client
Layer two

Our editor

A full timeline, preview and assistant panel. The agent's edits stream in over SSE, so the tracks redraw as the work happens.

apps/web · TanStack Start
Layer three

The encode itself

When a job needs the real file, the agent writes the ffmpeg filter graph and runs it in a locked-down container.

ffmpeg · ffprobe · python
# 1 · the harness
npx @truefoundry/trueforge@latest          → localhost:8790

# 2 · the timeline tools
cd apps/agent && bun run start            → localhost:8941

# 3 · wire them together (any one key is enough)
ANTHROPIC_API_KEY=sk-... bun run setup

# 4 · the editor
bun run dev:web                           → localhost:5173
00:00:36 Say it

Ask in a sentence.
Watch the tracks move.

Every ask below runs real tools against real state. Clip ids, source offsets and frame boundaries are the agent's problem, not yours.

Remove the silences

Finds every silent range on the voice track, tells you what will go, and ripple-deletes it across all tracks so the gaps close.

find_silences → remove_silences

Caption every clip

Fans out one sub-agent per clip to transcribe in parallel, merges the results, and lays timed captions on their own track.

transcribe_clip × N → add_captions

Cut this to the beat

Reads the tempo off the music track and splits on the beat grid, both halves still frame-accurate.

detect_beats → split_clip

Duck the music under the voiceover

Sets clip volume where the voice track is speaking and puts it back where it is not.

get_project → set_volume

Grade it warmer and add grain

Writes the ffmpeg filter graph, runs it in the media sandbox, then probes the output to confirm it is what you asked for.

probe_media → run_ffmpeg

Kill the room tone

Denoises the voice track in the sandbox and leaves the original file untouched next to it.

run_ffmpeg · afftdn

Sixteen timeline tools in all. Five read, seven write and undo, three destructive, one gated export. The destructive ones carry MCP's destructiveHint, which is what makes the harness stop and ask you first.

00:00:58 Pull it in

Need a logo?
It goes and gets one.

The agent reaches the live web through Bright Data, so a logo, a product shot or a reference frame is one sentence away from being on your timeline. The connector attaches deferred: it costs no context until a task actually needs it.

Find it

search_engine

Live search results, not a training-set memory of what a brand looked like two years ago.

Take it

scrape_as_markdown

Pulls the page down clean, so the agent can lift the asset and the copy around it.

00:01:16 Add a tool mid-call

A new skill is a
line in a config.

On the call Bro, can you add an MCP for motion graphics? I want to use it in this video.
You Sent to your agent.

Every capability here is an MCP server, so adding one is a name in a list and a restart, not a release. The agent picks up the new tools on its next turn and starts using them in the same conversation.

EDITAI_CONNECTORS=exa,bright-data,motion-graphics bun run setup

✓ motion-graphics   attached   read-only, deferred
✓ agent updated     14 connectors → tools live on the next turn

Catalog servers attach by name, OAuth ones authorise in chat, and anything you host yourself attaches the same way. Read-only and deferred by default, so a connector you rarely use does not crowd the agent's context.

00:01:34 Where it runs

Nothing the agent
writes runs on your box.

Two sandboxes, because the two kinds of work need different boundaries.

Daytona

Harness sandbox

For the computation the agent should not estimate: arithmetic, parsing, anything it would otherwise guess at. Runs remotely, registered the moment the key is present.

exit 0 · 338350
Container

Media sandbox

Every ffmpeg call runs in a throwaway container: no network, capped memory and CPU, 256 pids, non-root, one mounted workspace, hard timeout. Python there asks for approval first, because a script with the workspace mounted can delete your source media.

--network none · --pids-limit 256
00:01:52 Reviewed by Qodo

Every line here was
reviewed by Qodo.

Not a badge. Eight findings across three reviews, each one either fixed or answered with a proof, and a merge gate that reads Qodo's structured verdict rather than its prose.

8Findings raised 7Real, fixed 1Checked, rejected 5Regression tests added
PR #3 Duplicate clip ids after repeated ripple deletes. A clip cut twice produced the same id twice, breaking lookup, deletion and React keys. The test suite had missed it because the existing test asserted the buggy id as correct. FIXED
PR #3 Export announced before the file existed. The record was committed, notifying subscribers, and only then was the file written. FIXED
PR #3 Session restore leaked its stream on unmount. It set state on a gone component and left the connection open. FIXED
PR #3 Setup posted API keys over plaintext HTTP. It now refuses to do that to anything but localhost. FIXED
PR #3 The trim bound was called wrong, and was not. The source expression expands to the correct source time; the code accepts exactly up to the limit and rejects one frame past it. Two tests now pin that boundary. REJECTED
PR #2 Sandboxed Python could delete the source media. The argument guard could not catch it, and the container is no defence, since the workspace is exactly what it is meant to reach. The tool now asks for approval first. FIXED

Qodo publishes no check run and no approving review, so GitHub's own auto-merge has nothing to gate on. The workflow in this repo is that missing gate: it reads only the structured counter chips, never the prose, because Qodo quotes findings verbatim and a pull request can put the words "no issues found" into its own diff. It binds the verdict to the reviewed commit and merges with --match-head-commit, so a push racing the merge is rejected rather than slipped in.

And the video you
just watched?

It cut itself.