capcut-cli-david

August 7, 2026 · View on GitHub

One CLI to build, edit, and inspect CapCut draft_content.json projects — combining cutcli's creation power (keyframes, Ken Burns, animations) with capcut-cli's inspection surface (segments, tracks, SRT export), plus a psycho-build YAML pipeline for assembling complete TikTok-format vertical shorts in one command.

npm version CI Node ≥ 18 License: MIT

Why this exists

There are two existing tools in this space and each covers half the surface. Rene Zander's capcut-cli is excellent at inspecting existing drafts — segments, tracks, materials, SRT export — but is effectively read-only when it comes to creation primitives. The closed-source cutcli Go binary covers the creation half — keyframes, Ken Burns, animations, stickers, filters — but offers nothing for inspection or pipelined assembly.

capcut-cli-david is the fork that does both. One binary (capcut-david), zero runtime dependencies, fully scriptable. On top of the union of those two surfaces, it ships a psycho-build command that consumes a single YAML manifest (images + audio + captions) and produces a complete TikTok-format (1080×1920) vertical draft — deterministic via --seed, ready to open in CapCut.

The audience: anyone scripting CapCut drafts. TikTok creators automating shorts, video automation pipelines, AI-driven video assembly, and Claude Code skills (a bundled capcut-david skill ships in the package).

Comparison

Featurecutcli (upstream Go)capcut-cli (renezander030)capcut-cli-david
Inspect segments / tracks / materials
Export SRT
Edit (shift / speed / volume / trim / opacity / set-text)partial
Add video / audio / text
Keyframes (add-keyframe, any property)✅ (mid-level API)✅ (CLI flag)
Ken Burns (ken-burns)✅ (manual keyframes)✅ (one command)
Templates (save / apply)
Long-form → short (cut)
Batch JSONL stdin (batch)
YAML manifest pipeline (psycho-build)
Test suiteminimalminimal212 tests, 93%+ coverage
Schema reference docspartial (zh-CN)minimalfull (docs/draft-schema/)
Lint / typecheck / CI matrixnonenoneBiome 2 + tsc + Node 18/20/22 × Ubuntu/macOS/Windows
Node versionn/a (Go)≥ 18≥ 18
Runtime depsn/aminimalzero
LicenseunclearMITMIT

(Rows for cutcli reflect the closed-source Go binary's observed output and may be incomplete.)

Install

npm install -g capcut-cli-david
# CLI binary: capcut-david
capcut-david --help

Requires Node ≥ 18. Zero runtime dependencies.

Quickstart

Inspect an existing draft

capcut-david info ./MyProject -H
capcut-david tracks ./MyProject -H
capcut-david segments ./MyProject --track text
capcut-david export-srt ./MyProject > subs.srt

Add Ken Burns to a still image

capcut-david add-video ./MyProject ./photo.jpg 0s 4s
# Take the segment id printed above, then:
capcut-david ken-burns ./MyProject <segment-id> --from 1.0 --to 1.15

Build a complete TikTok draft from YAML

capcut-david psycho-build examples/psycho/manifest.example.yaml \
  --out ./build/my-short \
  --seed 42

--seed makes the build deterministic — same manifest + same seed → byte-identical draft, so you can diff outputs in CI. See examples/psycho/ for the full manifest example and minimal asset stubs.

A minimal manifest:

title: Paranoia Spiral
resolution: { width: 1080, height: 1920 }
fps: 30

images:
  - { path: ./assets/img1.jpg, duration: 3s, ken_burns: { from: 1.0, to: 1.3, curve: ease-out } }
  - { path: ./assets/img2.jpg, duration: 3s, ken_burns: { from: 1.3, to: 1.0, curve: ease-out } }

voice: { path: ./assets/narration.mp3, volume: 1.0 }
music: { path: ./assets/ambient.mp3,   volume: 0.25 }   # statically ducked

captions:
  srt: ./assets/captions.srt
  style: { font_size: 24, color: "#FFD700", align: 0 }

Commands

Full index — group by family. For per-flag reference, run capcut-david <command> --help.

Inspect

CommandPurpose
info <project>Draft summary: resolution, fps, duration, track + material counts
tracks <project>List tracks with id, type, segment count
materials <project> [--type <t>]List materials filtered by type (videos / audios / texts / …)
segments <project> [--track <id>]List segments, optionally filtered to one track
segment <project> <id>Detailed dump of a single segment
material <project> <id>Detailed dump of a single material
texts <project>All text segments with their content
export-srt <project>Emit captions as SRT to stdout

Edit (writes .bak before mutating)

CommandPurpose
set-text <project> <id> "<text>"Replace text content of a text segment
shift <project> <id> <±duration>Shift a single segment in time
shift-all --offset <±duration> [--track <t>]Shift every segment (optionally per-track)
speed <project> <id> <factor>Re-time a video/audio segment
volume <project> <id> <0..1>Set audio segment volume
trim <project> <id> <start> <end>Trim a segment to a sub-range
opacity <project> <id> <0..1>Set visual segment opacity
cut <project> <start> <end> --out <file>Long-form → short clipping

Create

CommandPurpose
init <name> --drafts <dir>Bootstrap an empty draft directory
add-video <project> <path> <start> <end>Append a video/image segment
add-audio <project> <path> <start> <end> [--volume]Append an audio segment
add-text <project> <start> <end> "<text>" [--font-size --color]Append a text segment
save-template <project> <id> <name> --out <file>Extract a segment as reusable template
apply-template <project> <template> <start> <end> "<text>"Apply a saved template

Animate (Phase C)

CommandPurpose
add-keyframe <project> <id> <time> --property <p> --value <v> [--curve <c>]Insert one keyframe on scale_x/scale_y/position_x/position_y/rotation/alpha. Curves: linear, ease-in, ease-out, ease-in-out.
ken-burns <project> <id> --from <s> --to <s> [--curve <c>]Paired scale_x + scale_y keyframes from t=0 to t=segment.duration. Default curve ease-out (CapCut "Cubic Out").

Batch

CommandPurpose
batch <project>Read JSONL ops on stdin ({"cmd": "...", ...}), apply atomically

Pipeline (Phase D)

CommandPurpose
psycho-build <manifest.yaml> [--out <dir>] [--seed <n>]Full TikTok-format draft from a YAML manifest

Discovery

CommandPurpose
query <term>|--all [--kind <k>] [--drafts <dir>]Search the drafts library for effects, filters, transitions, fonts (read-only, stateless)
make-preset --font <name|resource_id> [--out <file>]Generate a bare-font restyle preset from a font already used in your drafts
catalogue [--sync] [--kind <k>] [--dry-run] [--catalogue <path>]Mémoire persistante des ressources validées (nom → resource_id), annotable à la main

Output modes

JSON (default), human-readable (-H / --human), quiet (-q / --quiet).

capcut-david texts ./project | jq '.[].text'
capcut-david info ./project -H
capcut-david set-text ./project a1b2c3 "Fixed" -q && echo done

Time formats

1.5s, 500ms, +0.5s, -1s, 1:30, 0:05.5. Negative offsets allowed where they make sense (e.g. shift).

IDs

Segment and material IDs are UUIDs. The first 6+ chars work as a prefix match.

Documentation

Compatibility

  • CapCut: 5.x+ desktop on Windows + macOS. Both the cutcli-emitted draft shape (new_version: 167.x) and the CapCut-UI-emitted shape (169.x) load.
  • JianYing: 5.x is presumed-equivalent to CapCut 5.x. JianYing 6+ is unsupported — the on-disk draft_content.json is encrypted; capcut-david exits non-zero with a documented error. See COMPATIBILITY.md §5.
  • Node: ≥ 18 (engines.node in package.json). CI matrix covers Node 18 / 20 / 22 on Ubuntu / macOS / Windows.
  • Runtime deps: zero. Built entirely on the Node standard library.
  • Encoding: UTF-8 without BOM. Never re-save edited drafts via PowerShell Out-File without -Encoding utf8 — CapCut refuses BOM-prefixed JSON.

Project status

PhaseGoalVersionState
AFork + restructure baseline0.1.0shipped
BFixture-backed test suite (102 tests)0.2.0shipped
Cadd-keyframe + ken-burns (33 new tests)0.3.0shipped
Dpsycho-build YAML pipeline (39 new tests, 212 total)0.4.0shipped
ESKILL.md + polished docs + 1.0 graduation1.0.0in progress (0.5.01.0.0-rc.N1.0.0)

Aggregate test coverage on src/commands/* + src/draft.ts: 93%+ lines, 91%+ functions (CI gate: 80%).

Contributing

PRs welcome for bug fixes, schema validation, additional fixtures, and portability fixes. For new commands or behavioral changes, open an issue first to discuss scope and the upstream-sync implication.

  • Follow Conventional Commits.
  • Run npm test && npm run lint && npm run typecheck before submitting.
  • Portable bug fixes that apply to upstream capcut-cli are landed there too where reasonable — see UPSTREAM.md §4 (PR-back policy).

Acknowledgements

  • capcut-cli by renezander030 — the upstream this fork is built on. Provides the inspection surface and the modular draft helpers that everything else extends.
  • cutcli — closed-source Go binary whose draft output informed the schema reverse-engineering and inspired the creation primitives. No code copied; behaviour reproduced from on-disk JSON observation.
  • CapCut by ByteDance — the upstream product. This project is unaffiliated with ByteDance and operates only against locally-stored draft files.

License

MIT — see LICENSE and NOTICE.