faceless-cli
v1.1.11
Published
CLI for Faceless.so: create AI faceless videos, run automated series and publish to YouTube, TikTok, Instagram and more.
Downloads
1,178
Maintainers
Readme
Faceless CLI
Command line client for the Faceless.so public API: create AI faceless videos from a script, run automated series and publish to YouTube, TikTok, Instagram, X, Facebook, LinkedIn and Threads. Also ships a local MCP server so agents can use Faceless as tools.
API reference: https://faceless.so/api/v1/openapi.json
Install
npm install -g faceless-cliRequires Node 18 or newer. The package installs two equivalent commands: faceless and fcl.
Authentication
Create an API key in your team settings at https://faceless.so/team, then either log in once:
faceless loginThis verifies the key against GET /me and saves it to ~/.faceless/config.json (file mode 600). Or use an environment variable instead:
export FACELESS_API_KEY=fl_live_...
faceless whoamiKey precedence: --api-key flag, then FACELESS_API_KEY, then the config file. The base URL can be overridden with --api-url or FACELESS_API_URL. Use faceless logout to remove the saved key.
Commands
| Command | Description |
| ------------------------------ | --------------------------------------------------------------------- |
| faceless login | Save an API key to ~/.faceless/config.json (verified against /me) |
| faceless logout | Remove the saved API key |
| faceless whoami | Identify the caller (team, plan, scopes) |
| faceless credits | Credit balance and history |
| faceless videos create | Create a faceless video from a script (charges credits) |
| faceless videos captions | Caption an existing video or audio URL |
| faceless videos list | List the team's videos |
| faceless videos get <id> | Get one video |
| faceless videos update <id> | Update a video's name or per-platform post metadata |
| faceless videos status <id> | Poll video generation progress (--wait) |
| faceless videos render <id> | Render a generated video to MP4 (--wait) |
| faceless videos delete <id> | Delete a video |
| faceless renders get <id> | Poll render progress (--wait) |
| faceless series create | Create an automated video series |
| faceless series list | List the team's series |
| faceless series get <id> | Get one series |
| faceless series update <id> | Update a series (--paused / --no-paused to pause or resume) |
| faceless series delete <id> | Delete a series |
| faceless series generate <id>| Generate the next episode now (--wait) |
| faceless series episodes <id>| List a series' episodes |
| faceless posts publish | Publish a rendered video to a platform now |
| faceless posts schedule | Schedule a video to one or more platforms |
| faceless posts cancel <videoId> | Cancel a scheduled post |
| faceless calendar | Posting calendar for a date range |
| faceless accounts | List connected social accounts |
| faceless voices | List TTS voices |
| faceless options | List option catalogs (styles, niches, models, ...) |
| faceless assets create | Register a media asset by URL |
| faceless analytics | Cross-platform posting analytics |
| faceless mcp | Start the local MCP server over stdio |
Global options: --json, --api-key <key>, --api-url <url>. Run any command with --help for its flags.
Quickstart: create, render, publish
# Pick a voice and see what everything costs
faceless voices
faceless options --kind models
# 1. Create a video from a script and wait for generation to finish
# (storyboard 20 credits, motion_lite 50, motion_pro 100)
faceless videos create \
--script "Did you know the ocean has lakes and rivers of its own? ..." \
--voice-id EXAVITQu4vr4xnSDxMaL \
--model storyboard --wait
# 2. Render it to MP4 and wait for the download URL
faceless videos render 665f1b2a9c31a2b3c4d5e801 --wait
# 3a. Publish it to YouTube right now
faceless accounts
faceless posts publish --video-id 665f1b2a9c31a2b3c4d5e801 \
--platform youtube --title "The ocean has rivers underwater"
# 3b. Or set per-platform metadata and schedule it for later
faceless videos update 665f1b2a9c31a2b3c4d5e801 \
--youtube-title "The ocean has rivers underwater" \
--tiktok-title "underwater rivers are real #ocean"
faceless posts schedule --video-id 665f1b2a9c31a2b3c4d5e801 \
--platforms youtube,tiktok --scheduled-time 2026-08-01T18:00:00Z
# What is queued this week?
faceless calendar --start-date 2026-08-01 --end-date 2026-08-07More flows:
# Caption footage you already have
faceless videos captions --video-url https://example.com/clip.mp4 --wait
# A set-and-forget channel: one episode per day at 6pm
faceless series create --name "Deep sea facts" \
--source "Facts & stories" --niche "Ocean facts" \
--voice EXAVITQu4vr4xnSDxMaL --duration 60 \
--auto-post-time 18:00 --timezone America/New_York
faceless series generate 665f1b2a9c31a2b3c4d5e901 --wait
faceless series episodes 665f1b2a9c31a2b3c4d5e901JSON output and exit codes
Pass --json to print the raw API envelope ({ "success": true, "data": ... }). When stdout is not a TTY (pipes, scripts, CI), JSON is printed automatically, so faceless videos list | jq just works.
Errors are written to stderr as error (<type>): <message> with these exit codes:
| Exit code | Meaning |
| --------- | ---------------------------------------------------------------------- |
| 0 | Success |
| 1 | Any other error (invalid input, not found, conflict, network, timeout) |
| 2 | unauthorized or forbidden_scope |
| 3 | insufficient_credits |
| 4 | rate_limited |
On HTTP 429 the client retries once after the Retry-After interval (capped at 30 seconds). Every mutating request carries an auto-generated Idempotency-Key (override with --idempotency-key), so retries can never double-charge credits.
Waiting for async work
Generation and rendering are asynchronous. --wait (with --timeout <sec>, default 600) polls every 5 seconds until a terminal state:
videos create --waitandvideos captions --waitpollvideos statusuntil the video iscompletedorfailedvideos render <id> --waitpollsrenders getwith the returned renderId untildoneorerrorseries generate <id> --waitpolls the created episode's video statusvideos status <id> --waitandrenders get <id> --waitdo the same for something already in flight
posts publish is synchronous and returns the post URL directly.
MCP server
The CLI doubles as a local MCP server over stdio, exposing the Faceless API as tools (faceless_create_video, faceless_render_video, faceless_publish_post, and more). Add it to Claude Code:
claude mcp add faceless -- npx -y faceless-cli mcpMake sure FACELESS_API_KEY is set in the environment (or run faceless login first).
Prefer a hosted option? Faceless also serves a remote MCP endpoint at https://faceless.so/api/v1/mcp (Authorization: Bearer fl_live_...), no local install needed.
Links
- Faceless.so: https://faceless.so
- API keys: https://faceless.so/team
- OpenAPI spec: https://faceless.so/api/v1/openapi.json
