Result contract
Every tool, on every surface, returns the same shape.
Success
{
"success": true,
"output": "/absolute/path/to/file.mp4",
"metadata": {
"tool": "render",
"cleya_version": "0.6.0",
"duration_ms": 7660
}
}
Plus whatever that tool measured — frames, qa, score, checks, findings, outputs.
Output paths are always resolved to absolute before they are returned.
Failure
{
"success": false,
"error": "FFmpeg not found at \"ffmpeg\". Install FFmpeg or set ffmpeg_path in config.",
"code": "FFMPEG_ERROR",
"suggestion": "brew install ffmpeg"
}
Agents branch on code; humans read error.
Codes
| Code | Meaning |
|---|---|
VALIDATION_ERROR | Params failed validation — bad layer id, malformed spec, missing required field |
FFMPEG_ERROR | FFmpeg failed or is missing |
WHISPER_ERROR / WHISPER_NOT_FOUND | Transcription failed, or whisper.cpp is not installed |
DRAWTEXT_NOT_FOUND | FFmpeg lacks the libfreetype drawtext filter |
OUTPUT_EXISTS | Target file exists and overwrite was not set |
DURATION_EXCEEDS_LIMIT | Clip is longer than the platform allows |
NO_CANDIDATES | Analysis found nothing worth clipping |
Guarantees
- Overwrite protection. Any tool producing a file checks for an existing one and returns
OUTPUT_EXISTSunlessoverwrite: true. - Dependency checks up front. Missing FFmpeg features and Whisper are reported with an actionable message before a cryptic subprocess failure.
- Metadata on every success.
tool,cleya_versionandduration_ms, always.
Exit codes
The CLI exits 0 on success and 1 on failure, with the JSON body on stdout either way — so a shell can branch on the exit code and a program can parse the reason.