diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30ceb9e..2f958d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,3 +92,27 @@ jobs: cache: npm - run: npm ci - run: npm test + + python-client: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + python: '3.9' + - os: ubuntu-latest + python: '3.14' + - os: windows-latest + python: '3.9' + - os: windows-latest + python: '3.14' + - os: macos-latest + python: '3.14' + runs-on: ${{ matrix.os }} + name: Python client (${{ matrix.os }}, ${{ matrix.python }}) + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python }} + - run: python -m unittest discover -s python/tests -v diff --git a/CHANGELOG.md b/CHANGELOG.md index 0610bff..1569867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to capcut-cli are documented here. The format follows [Keep ## [Unreleased] +## [0.28.0] — 2026-10-03 + +### Added + +- `--active-timeline` explicitly follows a validated `Timelines/project.json` pointer on app builds without a verified storage fixture (#50). Invalid, deleted, symlinked or conflicting selected timelines are refused; normal defaults and write guards remain unchanged. Writes keep root and active IDs and preserve other timelines. +- `compile --into ` populates an existing empty project created in CapCut (#52). It preserves project identity, per-document app markers and unknown settings, stages content-correct media, and commits imported-media registration with timeline writes. Failed copies and commits clean up only newly owned assets; the shared store index is never rewritten. `--check`, `--plan` and `--dry-run` validate both spec and destination without writing. Nested layouts require active selection. Desktop acceptance on these opt-in paths remains unverified. + +- `describe --compact` emits a small command discovery index with names, summaries, usage, and write status. `describe --command ` returns complete contracts for selected commands; repeat the flag for several names. The full v2 command contract remains the default. Python client v0.1.3 forwards these options through `capcut.describe(compact=True, command="compile")`. + +### Fixed + +- Python client v0.1.3 parses quoted Windows `CAPCUT_CLI` paths without retaining surrounding quotes or losing backslashes. Escaped quotes, trailing backslashes, and empty arguments follow Windows argv quoting; malformed quotes fail before spawning a process. POSIX command quoting and shell-free execution remain unchanged. Python client regression tests now run on Linux, macOS, and Windows, including Python 3.9 and 3.14. + ## [0.27.0] — 2026-10-03 ### Added diff --git a/README.md b/README.md index 059426f..5350520 100644 --- a/README.md +++ b/README.md @@ -105,9 +105,20 @@ The host reads a draft and passes its JSON as tool input. The component itself h ## Release notes +> **New in v0.28.0:** opt-in active-timeline selection; compilation into empty app-created projects; compact command discovery and selection by name for agents; Windows command-path quoting fixed in Python client v0.1.3; and Python client CI on Linux, macOS, and Windows. Full details in the [changelog](./CHANGELOG.md). + > **New in v0.27.0:** content-safe media replacement; automatic import registration after replacement and relink; recursive, ambiguity-safe relinking; exact fractional-second compile boundaries; operation preflight and failed-build cleanup; payload-bound queue IDs; canonical project locks; bounded queue results; and local OTIO file/relative references. Full details in the [changelog](./CHANGELOG.md). -> **Fixed in v0.26.1:** ratio-only compile canvases and full source-media durations; JSON-escaped Windows fixture redaction with automatic leak verification; and active-timeline edits on the fixture-backed CapCut 8.7.0 Windows layout. A patched desktop round-trip remains pending. Full details in the [changelog](./CHANGELOG.md). +For an existing nested project, use `capcut diagnose --active-timeline` to inspect the selected document before editing. The opt-in follows the pointer on unverified builds and refuses invalid or conflicting selected documents; it does not bypass write guards. + +To populate a project that CapCut already owns, create an empty project in the app and quit CapCut, then run: + +```sh +capcut compile spec.json --into /path/to/app-created-project --active-timeline --check +capcut compile spec.json --into /path/to/app-created-project --active-timeline +``` + +Omit `--active-timeline` for a flat project without `Timelines/`. Every root and active mirror must be empty. The project keeps its name and registration; canvas and frame rate change only when supplied in the spec. Imported media is staged under the project, with registration and timeline backups committed together. Reopen, save, close and reopen in CapCut to check that edits persist. Automated safety tests cover these paths; desktop acceptance on your app build remains unverified. ## Built with capcut-cli @@ -136,6 +147,8 @@ JSON by default (pipe to `jq`); add `-H` for a human-readable table. Pass `--jia | **Long-form → short** | `cut` · `detect-scenes` (ffmpeg scene-cut detection) · `detect-silence` · `detect-retakes` (repeated takes) | | **Automation** | `serve` (stateless JSONL runner) · `migrate` · `doctor` · `sync-timelines` (8.7 mirror repair) | +`capcut describe --compact` lists command names, summaries, usage, and write status. Fetch a complete contract with `capcut describe --command compile`; repeat `--command` for several commands. Plain `capcut describe` still emits the full registry. + **Full reference** for every command, option, and exit code: **[docs/command-reference.md](./docs/command-reference.md)** (简体中文: [docs/command-reference.zh-CN.md](./docs/command-reference.zh-CN.md)). ## Sponsor diff --git a/README.zh-CN.md b/README.zh-CN.md index 358d2ed..ec02a4d 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -82,9 +82,9 @@ Claude Code 也可以把它作为插件加载: ## 发布说明 -> **v0.27.0 新增:** 按文件内容安全替换媒体;替换和重链接后自动更新媒体导入登记;递归搜索并报告同名歧义;精确处理小数秒时间边界;编译前校验操作并清理失败输出;将队列 ID 绑定到任务参数;统一项目锁;限制队列输出;以及解析 OTIO 的本地文件 URL 和相对路径。完整说明见[更新日志](./CHANGELOG.md)。 +> **v0.28.0 新增:** 显式选择活动时间线、向应用创建的空项目编译,以及精简的命令发现索引与按命令名筛选;Python 客户端 v0.1.3 修复 Windows 命令路径的引号解析,并在 Linux、macOS、Windows 上运行客户端 CI。详见 [更新日志](./CHANGELOG.md)。 -> **v0.26.1 修复:** 仅指定比例的编译画布与完整源媒体时长;对 JSON 转义的 Windows 路径进行 fixture 脱敏并自动检查泄漏;以及基于真实 fixture 的 CapCut 8.7.0 Windows 活动时间线编辑。修复后的桌面应用往返验证仍待完成。完整说明见[更新日志](./CHANGELOG.md)。 +> **v0.27.0 新增:** 按文件内容安全替换媒体;替换和重链接后自动更新媒体导入登记;递归搜索并报告同名歧义;精确处理小数秒时间边界;编译前校验操作并清理失败输出;将队列 ID 绑定到任务参数;统一项目锁;限制队列输出;以及解析 OTIO 的本地文件 URL 和相对路径。完整说明见[更新日志](./CHANGELOG.md)。 ## 使用 capcut-cli 构建 @@ -95,6 +95,17 @@ Claude Code 也可以把它作为插件加载: 项目描述须经其维护者确认。收录不代表背书或关联。 +使用 `capcut diagnose --active-timeline` 检查嵌套项目中的活动时间线。此显式选项依据 `Timelines/project.json` 选择文档;无效、已删除、符号链接或相互冲突的文档会被拒绝,现有写入保护仍然生效。 + +若要填充 CapCut 已创建的项目,先在应用中创建空项目并退出应用,然后运行: + +```sh +capcut compile spec.json --into /path/to/app-created-project --active-timeline --check +capcut compile spec.json --into /path/to/app-created-project --active-timeline +``` + +没有 `Timelines/` 的平面项目请省略 `--active-timeline`。所有根目录和活动时间线镜像必须为空;保留项目名称、身份和注册信息,只有 spec 明确指定时才修改画布和帧率。媒体写入项目的 assets 目录,时间线与媒体注册信息一起备份和提交。`--check`、`--plan`、`--dry-run` 均不写入。请在应用中打开、保存、关闭并重新打开,确认编辑保留;自动测试覆盖写入安全性,尚未验证此路径在各应用版本中的桌面往返行为。 + ## 常用命令 默认输出 JSON(可管道给 `jq`);加 `-H` 显示人类可读表格。加 `--jianying` 使用剪映枚举命名空间。运行 `capcut --help` 查看完整参数。 @@ -113,6 +124,8 @@ Claude Code 也可以把它作为插件加载: | **长视频切短** | `cut` · `detect-scenes`(ffmpeg 场景切点检测)· `detect-silence` · `detect-retakes`(重复口播段落)| | **自动化** | `serve`(无状态 JSONL 执行器)· `migrate` · `doctor` · `sync-timelines`(8.7 时间线镜像修复)| +`capcut describe --compact` 列出命令名、简介、用法和是否写入。`capcut describe --command compile` 返回指定命令的完整契约;重复 `--command` 可选择多个命令。不带选项的 `capcut describe` 仍输出完整注册表。 + **完整命令参考**(每个命令、参数与退出码):**[docs/command-reference.zh-CN.md](./docs/command-reference.zh-CN.md)**([英文原版](./docs/command-reference.md))。 ## 赞助 diff --git a/docs/command-reference.json b/docs/command-reference.json index 35e2b03..60a64aa 100644 --- a/docs/command-reference.json +++ b/docs/command-reference.json @@ -1,6 +1,6 @@ { "name": "capcut-cli", - "version": "0.27.0", + "version": "0.28.0", "schema_version": 2, "description": "Edit CapCut/JianYing draft_content.json directly. JSON in, JSON out.", "global_flags": [ @@ -80,7 +80,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": false, "prerequisites": [], "output": { @@ -103,7 +113,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": false, "prerequisites": [], "output": { @@ -230,6 +250,15 @@ "type": "path", "required": false, "description": "ffprobe binary." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -255,7 +284,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": false, "prerequisites": [], "output": { @@ -293,6 +332,15 @@ "type": "string", "required": false, "description": "Track or material type filter." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -317,7 +365,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": false, "prerequisites": [], "output": { @@ -350,7 +408,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -383,7 +451,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -440,6 +518,15 @@ "type": "time", "required": false, "description": "Shift only segments starting at or after this boundary; refuses a segment crossing it." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -474,7 +561,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -507,7 +604,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -545,7 +652,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -578,7 +695,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -629,6 +756,15 @@ "vtt" ], "default": "srt" + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -676,6 +812,15 @@ "type": "path", "required": false, "description": "Output path." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -728,6 +873,15 @@ "markers" ], "default": "skip" + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -784,6 +938,15 @@ "type": "path", "required": false, "description": "Template directory for --out." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -823,6 +986,15 @@ "type": "string", "required": false, "description": "Track or material type filter." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -852,7 +1024,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": false, "prerequisites": [], "output": { @@ -880,7 +1062,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": false, "prerequisites": [], "output": { @@ -964,6 +1156,15 @@ "type": "path", "required": false, "description": "ffprobe binary." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1060,6 +1261,15 @@ "type": "path", "required": false, "description": "ffprobe binary." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1170,6 +1380,15 @@ "type": "path", "required": false, "description": "Apply a make-preset style preset; explicit flags override preset values." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1273,6 +1492,15 @@ "type": "path", "required": false, "description": "ffprobe binary." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1345,6 +1573,15 @@ "type": "boolean", "required": false, "description": "Restore the full frame." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1388,6 +1625,15 @@ "type": "path", "required": false, "description": "Output path." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1440,6 +1686,15 @@ "type": "boolean", "required": false, "description": "Create a fresh same-type track directly above the source (the default)." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1496,6 +1751,15 @@ "type": "boolean", "required": false, "description": "Close the removed time span across every track; refuses crossing segments." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1571,6 +1835,15 @@ "hold" ], "default": "linear" + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1619,6 +1892,15 @@ "type": "time", "required": false, "description": "Transition duration." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1748,6 +2030,15 @@ "common_mask", "common_masks" ] + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -1791,6 +2082,15 @@ "type": "boolean", "required": false, "description": "Remove background blur." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2069,6 +2369,15 @@ "type": "path", "required": false, "description": "Apply a make-preset style preset; explicit flags override preset values." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2356,6 +2665,15 @@ "type": "path", "required": false, "description": "Apply a make-preset style preset; explicit flags override preset values." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2439,6 +2757,15 @@ "type": "time", "required": false, "description": "Combo duration." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2522,6 +2849,15 @@ "type": "time", "required": false, "description": "Combo duration." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2606,6 +2942,15 @@ "type": "string", "required": false, "description": "Target track name." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2640,7 +2985,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -2692,6 +3047,15 @@ "type": "number", "required": false, "description": "Fade-out seconds." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2735,6 +3099,15 @@ "type": "number", "required": false, "description": "Cover timestamp in milliseconds." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2820,6 +3193,15 @@ "required": false, "description": "Apply to the whole timeline (start 0, duration = draft duration).", "default": false + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2876,6 +3258,15 @@ "type": "string", "required": false, "description": "Custom resource ID." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -2979,6 +3370,15 @@ "type": "string", "required": false, "description": "Experimental: attach to one segment instead of the whole frame (segment ID)." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -3022,6 +3422,15 @@ "type": "path", "required": false, "description": "Output path." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -3084,6 +3493,15 @@ "type": "number", "required": false, "description": "Vertical position override." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -3122,6 +3540,15 @@ "type": "path", "required": false, "description": "Output path." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -3178,6 +3605,15 @@ "type": "boolean", "required": false, "description": "Commit only successful operations and exit 1 if any fail." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -3521,6 +3957,15 @@ "required": false, "description": "Emphasis size for --highlight-words matches, as a multiplier on the cue's base font size.", "default": 1.2 + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -3826,6 +4271,15 @@ "type": "number", "required": false, "description": "Background vertical offset." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -3864,6 +4318,15 @@ "type": "json", "required": false, "description": "Inline JSON or @file style ranges." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4098,6 +4561,15 @@ "required": false, "description": "Emphasis size for --highlight-words matches, as a multiplier on the cue's base font size.", "default": 1.2 + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4170,6 +4642,15 @@ "type": "string", "required": false, "description": "Anthropic model." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4237,6 +4718,15 @@ "type": "boolean", "required": false, "description": "Like --like, with the newest app-authored project in this draft's own drafts folder as the donor." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4294,6 +4784,15 @@ "type": "string", "required": false, "description": "Target track name." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4355,6 +4854,15 @@ "type": "boolean", "required": false, "description": "Remove chroma key." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4393,6 +4901,15 @@ "type": "boolean", "required": false, "description": "Turn smart matting off: writes the documented flag-0 matting object on the segment's video material (cache fields kept)." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4417,7 +4934,17 @@ "required": true } ], - "options": [], + "options": [ + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." + } + ], "mutates": true, "prerequisites": [], "output": { @@ -4472,6 +4999,15 @@ "type": "path", "required": false, "description": "Draft store root when the draft does not live inside a known one." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4515,6 +5051,15 @@ "type": "path", "required": false, "description": "Draft store root when the draft does not live inside a known one." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4589,6 +5134,15 @@ "type": "boolean", "required": false, "description": "Copy each file this run relinks into the draft's assets// and point the material at the copy, so the repaired draft is portable (video/audio only; skipped under --dry-run — a copy is a side effect no draft write rolls back)." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4641,6 +5195,15 @@ "type": "path", "required": false, "description": "ffprobe binary for duration/dimension detection." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -4680,6 +5243,15 @@ "required": false, "description": "Timeline columns.", "default": 60 + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -4830,10 +5402,123 @@ }, { "name": "describe", - "summary": "Emit the full command surface as JSON (agent tool spec).", - "usage": "capcut describe", - "positionals": [], - "options": [], + "summary": "Emit command contracts as JSON, optionally filtered by name or reduced to a compact discovery index.", + "usage": "capcut describe [--compact] [--command ]", + "positionals": [ + { + "name": "name", + "type": "string", + "required": false + } + ], + "options": [ + { + "name": "compact", + "flags": [ + "--compact" + ], + "type": "boolean", + "required": false, + "description": "Emit a discovery index with names, summaries, usage, and write status." + }, + { + "name": "command", + "flags": [ + "--command" + ], + "type": "enum", + "required": false, + "description": "Describe only this command; repeat to select several.", + "values": [ + "info", + "version", + "lint", + "tracks", + "segments", + "texts", + "set-text", + "shift", + "shift-all", + "speed", + "volume", + "trim", + "opacity", + "export-srt", + "export-ass", + "export-timeline", + "import-timeline", + "materials", + "segment", + "material", + "add-audio", + "tts", + "add-video", + "add-text", + "crop", + "cut", + "duplicate", + "remove", + "keyframe", + "transition", + "mask", + "bg-blur", + "text-style", + "restyle", + "text-anim", + "image-anim", + "add-sticker", + "mix-mode", + "audio-fade", + "add-cover", + "add-filter", + "bubble-text", + "add-effect", + "save-template", + "apply-template", + "make-preset", + "batch", + "import-srt", + "import-ass", + "text-ranges", + "caption", + "translate", + "migrate", + "add-sfx", + "chroma", + "matting", + "prune", + "register", + "rename", + "relink", + "timeline", + "projects", + "diff", + "concat", + "config", + "describe", + "completions", + "enums", + "catalogue", + "harvest-enums", + "doctor", + "diagnose", + "fixture", + "sync-timelines", + "restore", + "serve", + "decrypt", + "export", + "replace-media", + "init", + "quickstart", + "compile", + "render", + "detect-scenes", + "detect-silence", + "detect-retakes" + ] + } + ], "mutates": false, "prerequisites": [], "output": { @@ -5034,6 +5719,15 @@ "type": "string", "required": false, "description": "Effect id for an --add entry that carries both ids." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -5105,6 +5799,15 @@ "type": "path", "required": false, "description": "Write a redacted JSON diagnostic bundle." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -5147,6 +5850,15 @@ "type": "boolean", "required": false, "description": "Scan the finished bundle (SANITIZE_REPORT.json and README included) for residual home paths, emails, device ids and the account name, reporting file:line per finding and exiting non-zero on any. New bundles are checked automatically. With only a bundle directory as the argument, re-checks an existing bundle without rebuilding." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -5189,6 +5901,15 @@ "type": "boolean", "required": false, "description": "Also reconcile the nested Timelines// documents (draft_info.json, draft_content.json, template-2.tmp), each keeping its own GUID — the workaround verified on CapCut Mac 9.2.8 in issue #50, as an explicit opt-in. On Windows 8.7.0 active layouts only the selected timeline and root mirrors are reconciled, even with this flag. Timelines/project.json is never touched." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -5236,6 +5957,15 @@ "type": "boolean", "required": false, "description": "List snapshots." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -5622,7 +6352,7 @@ { "name": "compile", "summary": "Build a draft from a declarative JSON spec (the inverse of describe).", - "usage": "capcut compile [--out ] [--template auto|bundled|] [--data ] [--check | --plan]", + "usage": "capcut compile [--out | --into ] [--template auto|bundled|] [--data ] [--check | --plan]", "positionals": [ { "name": "spec.json", @@ -5650,6 +6380,15 @@ "required": false, "description": "Output path." }, + { + "name": "into", + "flags": [ + "--into" + ], + "type": "path", + "required": false, + "description": "Populate an existing empty app-created project, preserving its identity and store registration. Incompatible with --out, --drafts, --template and --data." + }, { "name": "drafts", "flags": [ @@ -5703,6 +6442,15 @@ "type": "boolean", "required": false, "description": "With --data: build only the rows that validate and exit 1 if any fail (batch's contract)." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": true, @@ -5835,6 +6583,15 @@ "type": "boolean", "required": false, "description": "Stream ffmpeg's progress to stderr instead of buffering it." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, @@ -6104,6 +6861,15 @@ "type": "boolean", "required": false, "description": "Force JSON output (the default; overrides -H)." + }, + { + "name": "active_timeline", + "flags": [ + "--active-timeline" + ], + "type": "boolean", + "required": false, + "description": "Explicitly follow the validated Timelines/project.json pointer on an unverified app build. Invalid, deleted or conflicting selected timelines are refused; write guards remain in force." } ], "mutates": false, diff --git a/docs/command-reference.md b/docs/command-reference.md index 9e1873b..32b8966 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -71,7 +71,7 @@ | `diff` | `capcut diff ` | no | Compare two drafts (segments/materials/tracks added/removed/changed). | | `concat` | `capcut concat [--out ]` | yes | Append one draft onto another's timeline (id-safe), write to --out or in place. | | `config` | `capcut config` | no | Show the resolved config (.capcutrc + effective defaults). | -| `describe` | `capcut describe` | no | Emit the full command surface as JSON (agent tool spec). | +| `describe` | `capcut describe [--compact] [--command ]` | no | Emit command contracts as JSON, optionally filtered by name or reduced to a compact discovery index. | | `completions` | `capcut completions ` | no | Generate shell completions (bash|zsh|fish). | | `enums` | `capcut enums [--jianying]` | no | List enum slugs (transitions, masks, effects, ...) by category. | | `catalogue` | `capcut catalogue [--kind ] [--limit ] [--jianying]` | no | Find a resource id by name across every category, harvested entries included. | @@ -86,7 +86,7 @@ | `export` | `capcut export --batch [options]` | yes | EXPERIMENTAL UI-automated render queue (macOS). | | `init` | `capcut init [--template auto\|bundled\|] [--drafts ] [--ratio \| --width --height ]` | yes | Create a new empty draft from a template. | | `quickstart` | `capcut quickstart [--video ] [--audio ] [--srt ] [--drafts ] [--template auto\|bundled\|] [--ratio \| --width --height ]` | yes | One-command first draft: create + add one input + lint + print the open-in-CapCut step. | -| `compile` | `capcut compile [--out ] [--template auto\|bundled\|] [--data ] [--check \| --plan]` | yes | Build a draft from a declarative JSON spec (the inverse of describe). | +| `compile` | `capcut compile [--out \| --into ] [--template auto\|bundled\|] [--data ] [--check \| --plan]` | yes | Build a draft from a declarative JSON spec (the inverse of describe). | | `render` | `capcut render [--out ] [options]` | no | Render a low-res ffmpeg proxy preview (trim+speed+audio, --burn-captions); not CapCut's final render. | | `detect-scenes` | `capcut detect-scenes