tldraw
Draw and visually collaborate with your agents on tldraw's canvas.
TLtldraw/tldraw51k近 7 天新增 105 个 star
Zero-dependency browser video editor AI agents drive via a JSON timeline over MCP; ffmpeg export.
https://github.com/user-attachments/assets/2430b854-168b-4a9a-af2e-489e5efa7543
FableCut is a Premiere-style non-linear video editor that runs entirely in your browser — and exposes its whole timeline as one JSON document. Edit it by hand, from the UI, or let an AI agent (Claude Code, Claude Desktop, or anything that speaks MCP/REST) cut your video for you while you watch the timeline update live.
Zero npm dependencies. One node server.js. That's it.

Most "AI video" tools hide the edit behind an API. FableCut flips that: the
project file is the interface. project.json describes media, clips,
tracks, effects, keyframes and transitions — any process that can write JSON
can edit video, and the open browser UI hot-reloads within ~150 ms via
server-sent events. A human and an agent can work on the same timeline at the
same time.
Editing
localStorage. Enable Link timeline and Project bin selection so picking a
timeline clip highlights its media in Project, and clicking a Project item
selects every timeline clip that uses it (off by default).fablecut_patch_project refuses to edit locked clips unless the
op says force: true.
fablecut_auto_duck.setFx patch op.setFxKeys.fablecut_denoise../media/ (same-origin after import). Remote SVG is refused. Agents use
fablecut_import_media with an https:// path. The URL is not kept as
media.src — that would taint the canvas and break export.exportFrame in project.json). Preview dims the overscan; drag the
Export frame handle to reframe (e.g. 16:9 canvas → 9:16 export). Fast export
crops to the frame; WebCodecs and Realtime export are disabled while a frame is set01:15:00,
1500, +30, 12.5; the IN / OUT readouts take typed times toocurrent / sequence duration; when markers are set, IN, marked duration, and OUT stack on the right. Export has a Range dropdown (Entire timeline / IN–OUT; defaults to IN–OUT when markers exist) so you can keep markers for split/trim and still export the full sequence. Enabling Limit constrains playback to the marked range and maps Home / End to the IN and OUT positions rather than the full timeline. t splits clips at the markers; ⇧t trims clips to the work (between marker in and marker out) area.fablecut_patch_project ops, on the same code.Look
setGrade patch op and read the result as numbers
with fablecut_scopes (levels, clipping, colour cast)setMask patch op and measure with fablecut_scopessetShape and setParent patch opssetMotionPath and setTextPath
patch opsfablecut_tracksetMatteMotion
speed and the engine time-remaps video and the
export audio mix (the fast-into-slow-mo reel move)Text
library/fonts/), and any
Google Font by name — loaded automaticallyboxW / boxH); further corner drags resize it (opposite
corner stays fixed; Ctrl/Cmd resizes from center; Shift
locks aspect). Inside a box, text wraps at the fixed font size by default;
enable Scale to fit to shrink the font so the whole block fits. V-align
(top / middle / bottom) places the text block vertically in the box. Set Box
W/H to 0 to return to hug-content sizing.Animated SVG clips
svg clip kind: CSS-@keyframes-animated SVGs render
frame-accurately in preview and export (the compositor freezes the
animation at any time). Agents can author their own vector overlays —
lower-thirds, confetti, sparkles — as plain .svg files. Starters included.Remake a reference video
node analyze.js ref.mp4, POST /api/analyze, or the
fablecut_analyze_reference MCP tool.Asset library
library/ folders surface as tabs in the UI: Elements (overlay art),
Sound FX, SVG — drop files in, the open editor refreshes liveExport
encoding-profiles.json (keeps rendering if you switch tabs). Encode and
upload run ahead of the compositor so a fast timeline is not stalled by
toBlob. The Export dialog has a profile selector; pin a project default
with encodeProfile in project.jsonfablecut_export runs the Fast export in the open editor,
or in a headless Chrome / Edge the server starts, and returns the file pathprojDur().npx -y fablecut # → http://localhost:7777
Your projects, media and exports go to ~/FableCut. Or run it from a clone:
git clone https://github.com/ronak-create/FableCut.git
cd FableCut
node server.js # → http://localhost:7777
Requirements: Node 18+ and a Chromium-based browser. ffmpeg on PATH is optional but recommended (fast export + upload remuxing). AI background removal fetches its model from a CDN on first use.
The server binds 127.0.0.1 only (v1.3.1+). To use it from another device on
your LAN, opt in explicitly: HOST=0.0.0.0 FABLECUT_ALLOWED_HOSTS=<your-ip> node server.js.
Drop media into the window (or ./media/), paste an HTTPS URL via + URL,
drag clips onto the timeline, edit, export.
To keep your work outside the checkout, set FABLECUT_DATA_DIR — it moves
project.json, media/, exports/, analysis/ and library/ to a directory
you choose. Leave it unset and everything stays in the repo, exactly as before.
/plugin marketplace add ronak-create/FableCut
/plugin install fablecut@fablecut
That registers the MCP server for you and adds three skills — edit-video,
remake-reel and motion-graphics. Your timeline and footage live in the plugin's own data
directory, so an update never touches them. Node 18+ and (optionally) ffmpeg
still need to be on your machine.
Everything an agent needs is in CLAUDE.md — the complete schema, semantics and recipes. Point any capable model at that file and it can operate the editor end to end.
📖 Browsable docs: the same manual as web pages, one page per topic (MCP tools, the
project.jsonschema, clip props, recipes, REST API, export): fablecut.space/docs.
Three equivalent control surfaces:
MCP (best for Claude Code / Claude Desktop) — register the bundled zero-dependency MCP server once:
claude mcp add -s user fablecut -- npx -y fablecut mcp
No clone or path needed; your work lives in ~/FableCut. From a clone,
point at the file instead:
claude mcp add -s user fablecut -- node "<path-to>/fablecut/mcp-server.js"
OpenCode can use the same stdio server from its project or global
opencode.json configuration:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"fablecut": {
"type": "local",
"command": ["node", "/absolute/path/to/FableCut/mcp-server.js"],
"enabled": true
}
}
}
For another MCP client, register a local stdio server with this equivalent command. The exact key names vary by client, but the command and arguments do not:
{
"name": "fablecut",
"transport": "stdio",
"command": "npx",
"args": ["-y", "fablecut", "mcp"]
}
(From a clone: "command": "node", "args": ["/absolute/path/to/FableCut/mcp-server.js"].)
The server is intentionally client-neutral. It speaks MCP over stdio and does not require Claude-specific environment variables. With a clone, keep the path absolute. Node 18 or newer either way.
Tools: fablecut_status (auto-starts the editor), fablecut_docs,
fablecut_get_project, fablecut_set_project, fablecut_patch_project,
fablecut_import_media, fablecut_analyze_reference,
fablecut_encode_profiles, fablecut_normalize_audio, fablecut_auto_duck,
fablecut_denoise, fablecut_export, fablecut_scopes, fablecut_track.
FableCut is also published on the official MCP registry as
io.github.ronak-create/fablecut
— each release ships an MCPB bundle (fablecut.mcpb) that MCPB-capable
clients can install directly.
The surface is token-efficient by design: agents patch the timeline with
small ops (fablecut_patch_project) instead of round-tripping the whole
document, read a compact one-line-per-clip summary
(fablecut_get_project {compact:true}), and fetch only the manual sections
they need (fablecut_docs {section:"props"}).
The file — read project.json, modify, bump revision, write. The UI
live-reloads.
REST — GET/PUT /api/project, POST /api/upload, POST /api/import-url,
GET /api/library, GET /api/export/profiles, SSE at /api/events. See
CLAUDE.md for the full list.
Example: ask Claude Code "cut these six clips to the beat markers, add a teal-orange grade, put a word-pop caption on top and a whoosh on every cut" — and watch the timeline rebuild itself.
Or hand it a reference: "here's a reel I like — analyze it and remake it with
my clips, same music". The agent calls fablecut_analyze_reference, gets the
blueprint (cuts, beats, BPM, energy, drop, extracted music), and rebuilds the
structure shot-for-shot with your footage.
Conflict-safe concurrent editing: the UI, the MCP tools, and direct
project.json writes all agree on a revision counter. If you edit a clip in
the UI while an agent is mid-task, the agent's next write is rejected (409 from
the REST API / a conflict error from fablecut_set_project) instead of
silently overwriting your change. The UI similarly detects when an agent write
supersedes a not-yet-saved local tweak and tells you with a toast instead of
dropping it silently.
server.js zero-dependency HTTP server: static hosting, REST API, SSE,
ffmpeg export pipeline
app.js the editor: timeline UI, compositor, keyframes, text engine,
SVG rasterizer, chroma key, exporters
index.html single-page UI
style.css dark editor theme
mcp-server.js stdio MCP server exposing the editor to AI agents
analyze.js reference-video analyzer: shots, beats/BPM, energy, drop,
music extraction (module + CLI)
CLAUDE.md the agent manual (schema + recipes) — also served by fablecut_docs
encoding-profiles.json
Fast-export ffmpeg presets (hot-reloaded)
project.json your timeline (created on first run; gitignored)
media/ project footage (gitignored)
analysis/ cached edit blueprints from /api/analyze (gitignored)
library/ default assets: elements/ sfx/ svg/ fonts/
exports/ finished renders (gitignored)
flowchart TD
subgraph group_interaction["Editing Experience"]
node_browser_ui["Browser Editor<br/>[app.js]"]
node_timeline_model["Timeline Model<br/>[app.js]"]
node_ruler_worker["Ruler Worker<br/>[ruler-worker.js]"]
end
subgraph group_project_media["Project And Media"]
node_project_store[("Project Store<br/>[paths.js]")]
node_media_store[("Media Store<br/>[paths.js]")]
node_asset_library[("Asset Library<br/>[server.js]")]
node_url_importer["URL Importer<br/>[import-url.js]"]
end
subgraph group_agent_api["Agent Control"]
node_rest_api["REST Server<br/>[server.js]"]
node_mcp_server["MCP Server<br/>[mcp-server.js]"]
node_sse_hub["Change Notifications<br/>[server.js]"]
end
subgraph group_playback_export["Playback And Export"]
node_compositor["Canvas Compositor<br/>[app.js]"]
node_audio_engine["Audio Engine<br/>[app.js]"]
node_audio_meter["Audio Meter<br/>[meter-worklet.js]"]
node_export_engine["Export Engine<br/>[server.js]"]
node_encoding_profiles["Encoding Profiles<br/>[encode-profiles.js]"]
end
subgraph group_analysis["Analysis Tools"]
node_reference_analyzer["Reference Analyzer<br/>[analyze.js]"]
end
node_human(("Human Editor"))
node_ai_agent(("AI Agent"))
node_ffmpeg["FFmpeg"]
node_human -->|"edits timeline"| node_browser_ui
node_ai_agent -->|"sends tools"| node_mcp_server
node_browser_ui -->|"updates project"| node_timeline_model
node_timeline_model -->|"persists JSON"| node_project_store
node_browser_ui -->|"calls REST"| node_rest_api
node_rest_api -->|"reads writes"| node_project_store
node_rest_api -->|"serves media"| node_media_store
node_rest_api -->|"lists assets"| node_asset_library
node_mcp_server -->|"checks server"| node_rest_api
node_mcp_server -->|"patches project"| node_project_store
node_mcp_server -->|"imports media"| node_url_importer
node_url_importer -->|"stores downloads"| node_media_store
node_rest_api -->|"downloads URLs"| node_url_importer
node_rest_api -->|"broadcasts changes"| node_sse_hub
node_sse_hub -->|"pushes changes"| node_browser_ui
node_timeline_model -->|"renders timeline"| node_compositor
node_timeline_model -->|"routes clips"| node_audio_engine
node_audio_engine -->|"measures audio"| node_audio_meter
node_browser_ui -->|"uploads frames"| node_rest_api
node_rest_api -->|"streams export"| node_export_engine
node_export_engine -->|"loads profile"| node_encoding_profiles
node_export_engine -->|"encodes video"| node_ffmpeg
node_reference_analyzer -->|"analyzes media"| node_ffmpeg
node_reference_analyzer -->|"writes music"| node_media_store
node_ai_agent -.->|"requests analysis"| node_reference_analyzer
node_browser_ui -.->|"draws ruler"| node_ruler_worker
click node_browser_ui "https://github.com/ronak-create/fablecut/blob/main/app.js"
click node_timeline_model "https://github.com/ronak-create/fablecut/blob/main/app.js"
click node_compositor "https://github.com/ronak-create/fablecut/blob/main/app.js"
click node_audio_engine "https://github.com/ronak-create/fablecut/blob/main/app.js"
click node_audio_meter "https://github.com/ronak-create/fablecut/blob/main/meter-worklet.js"
click node_rest_api "https://github.com/ronak-create/fablecut/blob/main/server.js"
click node_mcp_server "https://github.com/ronak-create/fablecut/blob/main/mcp-server.js"
click node_sse_hub "https://github.com/ronak-create/fablecut/blob/main/server.js"
click node_project_store "https://github.com/ronak-create/fablecut/blob/main/paths.js"
click node_media_store "https://github.com/ronak-create/fablecut/blob/main/paths.js"
click node_asset_library "https://github.com/ronak-create/fablecut/blob/main/server.js"
click node_url_importer "https://github.com/ronak-create/fablecut/blob/main/import-url.js"
click node_export_engine "https://github.com/ronak-create/fablecut/blob/main/server.js"
click node_encoding_profiles "https://github.com/ronak-create/fablecut/blob/main/encode-profiles.js"
click node_reference_analyzer "https://github.com/ronak-create/fablecut/blob/main/analyze.js"
click node_ruler_worker "https://github.com/ronak-create/fablecut/blob/main/ruler-worker.js"
classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_browser_ui,node_timeline_model,node_ruler_worker toneBlue
class node_project_store,node_media_store,node_asset_library,node_url_importer toneAmber
class node_rest_api,node_mcp_server,node_sse_hub toneMint
class node_compositor,node_audio_engine,node_audio_meter,node_export_engine,node_encoding_profiles toneRose
class node_reference_analyzer,node_human,node_ai_agent,node_ffmpeg toneIndigo
SVGs animate with plain CSS @keyframes. One convention: never hardcode
animation-delay — set --d: 0.4s instead, and the compositor drives time by
pausing all animations and rebasing their delays. Full rules + a skeleton in
CLAUDE.md; working
examples in library/svg/.
library/fonts/, OFL — see
LICENSES.md there) and a set of self-authored SVG overlays and animated
elements (library/elements/, library/svg/, MIT like the rest of the repo).library/sfx/ is yours to fill (gitignored): sound-effect sites typically
don't allow redistributing their files in a public repo, so FableCut doesn't —
library/sfx/README.md lists good free sources.media/).
Sidrune AI — One API for GPT, Claude, and other leading AI models. Sign up and get $3 in API credit.
Questions, ideas, showing off an edit, or want to help shape what's next? Join the FableCut Discord. Bugs and feature requests are still best filed as GitHub issues.
Draw and visually collaborate with your agents on tldraw's canvas.
TLtldraw/tldraw51k近 7 天新增 105 个 star
Search your local screen recordings, audio transcripts, and computer activity from screenpipe.
SCscreenpipe/screenpipe22k近 7 天新增 99 个 star
Transcribe local audio with FunASR and SenseVoice using private, on-device inference.
MOmodelscope/FunASR21k近 7 天新增 65 个 star
AI Skills, MCP Tools, and CLI for Unity Engine. Full AI develop and test loop. Use cli for quick setup. Efficient token usage, advanced tools. Any C# method may be turned into a tool by a single line. Works with Claude Code, Gemini, Copilot, Cursor and any other absolutely for free.
IVIvanMurzak/Unity-MCP4.4k近 7 天新增 37 个 star