An open source, agent-first Rust CLI for discovering, importing, and composing short-form social video assets.
The main working path is a TikTok trending sound ingestion pipeline built around Apify:
- discover trending sounds with
alien_force~tiktok-trending-sounds-tracker - resolve posts for each sound URL with a validated Novi actor using the repo's fixed
MUSICinput profile - normalize the resolver dataset and rank candidates by
digg_countdescending - keep one representative post for manifest/reporting while retaining the full ranked post set on disk
- download every usable resolved video directly from the resolver output
- extract audio locally with
ffmpegfor every downloaded video when possible - persist multi-asset video/audio bags, per-step metadata, and manifest entries in-repo
The CLI stays machine-readable throughout, so agents can inspect every step without scraping terminal text.
- Rust toolchain
ffmpegonPATH- an Apify token
For repo-local end-to-end testing, put the raw Apify token in a git-ignored file:
mkdir -p .secrets
printf '%s' "$APIFY_API_TOKEN" > .secrets/apify_api_token
chmod 600 .secrets/apify_api_tokenToken lookup order at runtime:
CAPCUT_CLI_APIFY_TOKEN.secrets/apify_api_token~/.config/capcut-cli/config.json
This lets coding agents run real imports from inside the repo without ever committing the key.
Check current auth state:
cargo run -- authPersist a token directly:
cargo run -- auth --apify "$APIFY_API_TOKEN"Persist the current CAPCUT_CLI_APIFY_TOKEN env var:
export CAPCUT_CLI_APIFY_TOKEN="$APIFY_API_TOKEN"
cargo run -- auth --from-envThe config file lives at ~/.config/capcut-cli/config.json. At runtime, CAPCUT_CLI_APIFY_TOKEN still overrides the file.
cargo run -- discover tiktok-sounds --country "United States" --period 7 --limit 5This returns live sound metadata from Apify, including song_id, clip_id, and the count of related_items kept only as debug metadata.
The resolver input shape is fixed in code, including limit: 20, but the exact Novi actor id is supplied at runtime so agents can point the CLI at the validated actor without patching the repo again.
Use a one-off flag:
cargo run -- library sound import-tiktok-trending \
--resolver-actor-id "<novi actor id>" \
--limit 1Or set an env var once:
export CAPCUT_CLI_TIKTOK_SOUND_RESOLVER_ACTOR_ID="<novi actor id>"cargo run -- library sound import-tiktok-trending \
--resolver-actor-id "<novi actor id>" \
--country "United States" \
--period 7 \
--limit 3 \
--max-posts 20 \
--download-attempts 5What the importer does for each sound:
- writes
trend.jsonwith the trend actor payload - writes
posts.jsonwith the raw Novi resolver dataset plus the exact resolver input profile - writes
selection.jsonwith normalized candidates ranked by likes - attempts every ranked candidate retained by
--max-postsand keeps every successfully downloaded video asset - extracts audio into a matching file under
audios/for each downloaded video when extraction succeeds - keeps a representative asset pair for manifest/report compatibility
- writes
download.jsonand a summarymetadata.json - merges the result into
library/sounds/manifest.json
The ranking strategy is explicit and simple: digg_count desc, then resolver order.
--max-posts caps the ranked candidates retained locally and attempted for download after the resolver returns its fixed limit: 20 dataset.
--download-attempts is now the per-candidate retry budget for direct media download, not a cap on how many ranked posts are attempted.
Imported sounds are written under library/sounds/imported/<slug>/:
trend.jsonposts.jsonselection.jsondownload.jsonmetadata.jsonvideos/audios/
The top-level manifest records provenance, the resolver actor id, the download method, representative media paths, multi-asset directory paths, and downloaded/extracted asset counts.
Install the latest release archive for the current machine:
./scripts/install-from-github-release.shOverride the target install directory if needed:
./scripts/install-from-github-release.sh --bin-dir "$HOME/.local/bin"Once the CLI is installed, update it in place:
capcut-cli updateWhen capcut-cli update is run from a repo build such as cargo run, it defaults to installing ~/.local/bin/capcut-cli. Override that explicitly if you want a different target path:
cargo run -- update --bin-path "$HOME/.local/bin/capcut-cli"Release automation is split into three GitHub Actions workflows:
.github/workflows/release-please.ymlupdates release PRs and tags/releases from pushes tomain.github/workflows/build-release-binaries.ymlbuilds release archives on pushes tomain.github/workflows/publish-release-assets.ymlattaches packaged archives to published GitHub releases
Release archive names match the update/install path exactly: capcut-cli-<target>.tar.gz, with the capcut-cli binary at archive root.
cargo run -- auth
cargo run -- auth --apify <token>
cargo run -- auth --from-env
cargo run -- discover tiktok-sounds --limit 10
cargo run -- discover x-clips --query "ai agents" --limit 10
cargo run -- library plan sound
cargo run -- library sound import-tiktok-trending --resolver-actor-id "<novi actor id>" --limit 3 --max-posts 20 --download-attempts 5
cargo run -- update --bin-path "$HOME/.local/bin/capcut-cli"
cargo run -- compose --sound sound_123 --clip clip_a --clip clip_b --duration-seconds 30discover x-clips is still a planning stub. The TikTok import path is the only live end-to-end ingestion pipeline in the repo today.
Downloaded media should be treated as research and prototyping assets unless rights have been separately verified. The importer records provenance and rights notes so the local library does not lose source context.
skills/capcut-cli/SKILL.mdfor operating the CLIskills/apify/SKILL.mdfor safe live Apify usage, local secret handling, and end-to-end smoke-test examples