Same pixels. No GPU. No watermark.
A GPU-less Linux box runs the compositor the apps ship — wgpu on lavapipe, ffmpeg as a subprocess. CLI overlay is None. The Mac app free tier is watermarked; that is an app policy, not the engine's.

LinuxSmoke.promo at 5.5 s — 1280×720, rendered on lavapipe. Caption asks the question. Kitchen-sink handshake: clip + audio, image, palette, easing, a waiting keyframe.
promo-cli sets ExportSettings.overlay = None — “The CLI is the oracle and renders clean; watermark policy is the apps' concern.” Free exports through the Mac app carry the PromoShot watermark. CI output is clean.One-liner from GitHub Releases
v0.2.1 ships promo + promoshot-mcp as linux-x64 and macos-arm64 tarballs. No Rust toolchain required.
# Linux x64
curl -fsSL -o promoshot.tar.gz \
https://github.com/GarAlex/promoshot/releases/download/v0.2.1/promoshot-v0.2.1-linux-x64.tar.gz
tar -xzf promoshot.tar.gz
install -m 0755 promo promoshot-mcp ~/.local/bin/
# macOS Apple silicon
curl -fsSL -o promoshot.tar.gz \
https://github.com/GarAlex/promoshot/releases/download/v0.2.1/promoshot-v0.2.1-macos-arm64.tar.gz
tar -xzf promoshot.tar.gz
install -m 0755 promo promoshot-mcp ~/.local/bin/
promo validate /ABS/PATH/Promo/LinuxSmoke.promo --json
promo still /ABS/PATH/Promo/LinuxSmoke.promo --time 5.5 --jsonReleases: github.com/GarAlex/promoshot/releases. Point MCP at the same binaries — see /mcp.
Docker
The image is the whole render environment: server, CLI, ffmpeg, lavapipe, fonts. A client needs nothing on the host but Docker. Examples are baked in — prove it with no mount by rendering /usr/local/share/promoshot/examples/ProductCard.promo.
docker pull ghcr.io/garalex/promoshot-mcp
# or, from the repo:
docker build -t promoshot-mcp .{
"mcpServers": {
"promoshot": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/ABS/PATH/Promo:/projects",
"promoshot-mcp"
]
}
}
}PROMOSHOT_WORKSPACE=/projects. Registry manifest: server.json → ghcr.io/garalex/promoshot-mcp.
What a headless box needs
ffmpeg/ffprobeon PATH (video)mesa-vulkan-drivers+libvulkan1— lavapipe ICD- Fonts:
fonts-liberation,fonts-dejavu-core - Building from source: rustc 1.98+ (distro 1.85 is too old for icu_*/image)
# wgpu: Backends::PRIMARY, HighPerformance, force_fallback_adapter=false
# On Linux that is Vulkan → lavapipe if there is no GPU.
cargo build --release -p promo-cli -p promoshot-mcp
# binaries: target/release/promo target/release/promoshot-mcp
promoshot-mcp --workspace /ABS/PATH/Promo --root /ABS/PATH/PromoValidate before render. ok means it will render. Inspect lists layer ids: promo inspect /ABS/PATH/Promo/LinuxSmoke.promo --json(flag after the path).
If wgpu / lavapipe fails
Install mesa-vulkan-drivers + libvulkan1 and re-check vulkaninfo --summary for llvmpipe.GpuContext does not set force_fallback_adapter. Without an adapter the CLI errors no GPU adapter available — do not fake screenshots.