On this page
CLI or MCP?
Use the CLI for scripts and CI, or use MCP for typed calls from an agent host.
CLIDirect process control with exit codes.MCPStdio tools with structured content.analyzeAdaptive evidence with exact source timestamps.Plan fileVersioned JSON with retained ranges and output settings.shareUploads a validated ZIP and returns a 24-hour link.Common workflows
These are the shortest paths from a local video to a checked archive.
Inspect a video
Read metadata, exact frame timing, and the detected crop before you create a plan.
npx -y chrona-cli@0.2.0 --json probe ./video.mp4Extract a range with a cut
Retain 00:02 through 00:12, remove 00:05 through 00:07, and write a ZIP.
npx -y chrona-cli@0.2.0 --json extract ./video.mp4 \
--start 00:02 \
--end 00:12 \
--cut 00:05..00:07 \
--output frames.zipSave the edit, then reuse it
A plan stores decisions, not frames. Run it again with the same source or pass a new output path.
npx -y chrona-cli@0.2.0 --json plan ./video.mp4 \
--cut 00:05..00:07 \
--fps 30000/1001 \
--write edit.chrona.json
npx -y chrona-cli@0.2.0 --json extract ./video.mp4 \
--plan edit.chrona.json \
--output frames.zipShare a completed archive
Validate locally, then upload only the finished ZIP. Links expire after 24 hours.
npx -y chrona-cli@0.2.0 --json share ./frames.zipBrowser actions in the CLI
The browser editor and native surfaces use the same edit outcomes and manifest semantics.
Open a local video
Pass a local path to probe, plan, estimate, or extract.
Read video details
Run probe. Metadata includes dimensions, codec, rotation, color, HDR, timing mode, and rates.
Detect solid borders
Use the default --crop auto mode. The returned rectangle is in displayed-pixel coordinates.
Trim the start and end
Use --start and --end. The retained interval is half-open and clamped to the source.
Remove many sections
Repeat --cut START..END. Overlapping and touching cuts merge.
Keep original timing
Use --fps original. The result follows the source frame boundaries, including VFR timing.
Choose a fixed rate
Use --fps detected, a decimal, or a rational. Frames are duplicated or skipped, never interpolated.
Estimate the ZIP size
Run estimate. The result is approximate and includes sampleCount and displayedResolution.
Export lossless PNG frames
Keep --quality 100. PNG compression level changes encoding effort only.
Create a smaller ZIP
Use --quality 50 through --quality 99. This resizes frames and quantizes RGB colors; it is not lossless.
Inspect frame previews
Run frame with a one-based frame number.
Download the ZIP
Use extract with a ZIP output path, or download a shared artifact.
Create a 24-hour link
Run share on a validated finished ZIP, up to 4 GB.
Open a shared ZIP
Run download on the share URL. The archive is validated before success.
Cancel active work
Send SIGINT or SIGTERM to the CLI, or cancel the MCP request. Active native processes receive the abort signal.
CLI reference
Each command has a stable anchor, a copyable invocation, a result shape, and recovery guidance.
doctor
Check that FFmpeg and FFprobe can run.
npx -y chrona-cli@0.2.0 --json doctor- Returns ready plus one object for each binary. Each binary includes available, path, and version; unavailable binaries also include error.
- Result shape
{ ready: boolean, ffmpeg: BinaryStatus, ffprobe: BinaryStatus }- Recovery
- If ready is false, reinstall the package or pass explicit binary paths. Exit code 3 covers a missing binary and a binary that cannot run.
analyze
Create or reuse a local animation-analysis session.
npx -y chrona-cli@0.2.0 --json analyze ./reference.mp4 --intent replicate- Scans every source frame at a bounded analysis resolution while preserving FFprobe presentation timestamps.
- Returns events, activity segments, attention regions, recommended inspections, and a labeled overview image. Matching source and options reuse the cached analysisId.
- Result shape
{ analysis: AnimationAnalysisV1, modelBrief: string, overviewPath: string, cacheHit: boolean, exportedTo?: string }- Recovery
- Correct the source path or range, then retry. Use --cache-dir when the default cache location is unavailable.
inspect
Render one analyzed segment or a batch of exact frames.
npx -y chrona-cli@0.2.0 --json inspect ANALYSIS_ID --segment segment-1- Pass exactly one of --segment or --frames. Segment inspection supports adaptive, event, uniform, or complete sampling.
- Exact-frame inspection can render a labeled strip or grid at preview or full resolution, optionally cropped to an attention region.
- Result shape
{ inspection: AnimationInspection, output?: string }- Recovery
- Use an analysisId and frame or segment IDs returned by analyze. Pass --overwrite before replacing a copied image.
cache
Inspect or clean the local animation-analysis cache.
npx -y chrona-cli@0.2.0 --json cache status- cache status reports the cache path, entry count, and bytes. cache clean removes expired entries, entries older than --older-than, or every entry with --all.
- Result shape
status: { path, entries, bytes } | clean: { path, removedEntries, removedBytes }- Recovery
- Pass --cache-dir when using a non-default analysis cache. Cleaning an empty cache succeeds without removing files.
probe
Read metadata, presentation timestamps, and an optional solid-border crop.
npx -y chrona-cli@0.2.0 --json probe ./video.mp4- The result has metadata, autoCrop, and frames. Add --fast to omit frames after the metadata scan. Add --no-auto-crop to set autoCrop to null.
- Frame timestamps are seconds from the probed source start. Each frame record has timestamp, sourceTimestamp, and duration.
- Result shape
{ metadata: VideoMetadata, autoCrop: CropRectangle|null, frames?: FrameBoundary[] }- Recovery
- Fix the input path or codec when the file cannot be opened. Use --ffmpeg-path and --ffprobe-path when the native tools are not found.
plan
Create a versioned edit plan without writing frames.
npx -y chrona-cli@0.2.0 --json plan ./video.mp4 \
--start 00:02 \
--end 00:12 \
--cut 00:05..00:07 \
--fps 30000/1001 \
--quality 80 \
--write edit.chrona.json- The result is { plan, estimatedFrames }. The written plan is schemaVersion 2 and includes the retained half-open ranges, FPS mode, crop, quality, archive, and source identity.
- The default range is the full source. The default FPS mode is original, the default crop is auto, the default quality is 100, and the default archive is zip.
- Result shape
{ plan: PlanV2, estimatedFrames: integer }- Recovery
- Edit range, time, FPS, or crop validation errors before retrying. A plan file is not an intermediate video and never contains frames.
estimate
Estimate frame count and output bytes from three PNG samples.
npx -y chrona-cli@0.2.0 --json estimate ./video.mp4 --plan edit.chrona.json- The result has frameCount, estimatedBytes, averageFrameBytes, sampleCount, quality, and displayedResolution.
- The estimate is approximate. It applies the plan crop, FPS mode, retained ranges, and quality before sampling.
- Result shape
{ frameCount: integer, estimatedBytes: integer, averageFrameBytes: integer, sampleCount: integer, quality: integer, displayedResolution: Resolution }- Recovery
- Treat estimatedBytes as a planning value, not an archive-size guarantee. Retry after correcting the source or plan when sampling fails.
extract
Write continuous, one-based PNG frames and a manifest to a ZIP or directory.
npx -y chrona-cli@0.2.0 --json --progress json extract ./video.mp4 \
--plan edit.chrona.json \
--output frames.zip- A successful result has dryRun, output, archive, frameCount, bytes, and manifestSchemaVersion. The manifest is schema v4.
- ZIP entries are <root>/frames/frame_000001.png and <root>/manifest.json. Directory output has frames/ and manifest.json at its root.
- Use --dry-run to return the resolved plan and FFmpeg command without creating output. Use --progress json for JSON Lines on stderr.
- Result shape
{ dryRun: false, output: string, archive: zip|directory, frameCount: integer, bytes: integer, manifestSchemaVersion: 4 }- Recovery
- Without --overwrite, an existing target is an error. Temporary frames are removed on cancellation unless --keep-temp is set. A failed archive write can leave a partial final target; validate or remove it before retrying.
validate
Validate a Chrona ZIP or extracted directory.
npx -y chrona-cli@0.2.0 --json validate ./frames.zip- Validation checks the manifest schema, frame count, one-based numbering, expected frame names, required entries, and the first PNG dimensions.
- The command accepts a ZIP or a directory and returns valid, type, path, frameCount, and schemaVersion.
- Result shape
{ valid: true, type: zip|directory, path: string, frameCount: integer, schemaVersion: 4 }- Recovery
- Inspect the first validation error. Do not use an archive with a missing frame, mismatched manifest, or wrong dimensions.
frame
Copy one full-size PNG from a Chrona ZIP or directory.
npx -y chrona-cli@0.2.0 --json frame ./frames.zip 42 --write frame-42.png- Frame numbers are one-based and map to frame_000001.png, frame_000002.png, and so on. The result has output, frameNumber, bytes, width, and height.
- If --write is omitted, the default output is frame_000042.png in the current directory.
- Result shape
{ output: string, frameNumber: integer, bytes: integer, width: integer, height: integer }- Recovery
- Use a positive frame number within the manifest range. An existing output requires --overwrite.
download
Download a shared archive, then validate it before returning success.
npx -y chrona-cli@0.2.0 --json download https://chrona.fyi/artifacts/TOKEN --output frames.zip- If the URL does not end in /download, the command appends that path. The result has output, bytes, and frameCount.
- The response is written to a .part file, renamed into place only after the download completes, and validated before success.
- Result shape
{ output: string, bytes: integer, frameCount: integer }- Recovery
- Use a current share URL and retry network failures. Partial .part files are removed after a failed download. An existing output requires --overwrite.
schema
Print the plan, manifest, or analysis JSON Schema.
npx -y chrona-cli@0.2.0 --json schema analysis- The result has name and schema. Plan is schema v2, manifest is schema v4, and analysis is schema v1.
- Result shape
{ name: plan|manifest|analysis, schema: object }- Recovery
- Pass plan, manifest, or analysis. An unknown name is an argument error with exit code 2.
mcp
Run the MCP server over stdio.
npx -y chrona-cli@0.2.0 mcp- The process speaks MCP on stdin and stdout. Startup errors are written to stderr. Pin the package version in the host configuration.
- Result shape
MCP protocol messages on stdout- Recovery
- Check the host configuration, Node.js version, and binary environment. Close the host connection to stop the process.
Options reference
Defaults and validation are part of the contract. Paths are resolved on the machine running the command.
Global options
--jsonApplies to All CLI commandsWrite one command result to stdout as JSON. Errors use the error object described above.
Default: offRepeatable: NoConflicts: No conflict.--progress tty|json|noneApplies to analyze, extract, shareWrite progress to stderr. json emits one JSON object per line; none suppresses progress.
Default: ttyRepeatable: NoConflicts: No conflict.--quietApplies to All CLI commandsSuppress the human-readable result. It does not suppress JSON output or errors in JSON mode.
Default: offRepeatable: NoConflicts: No conflict.
Native tools
--ffmpeg-path PATHApplies to doctor, analyze, inspect, probe, plan, estimate, extractChoose the FFmpeg executable. The option wins over CHRONA_FFMPEG, the bundled binary, and PATH.
Default: resolvedRepeatable: NoConflicts: No conflict.--ffprobe-path PATHApplies to doctor, analyze, probe, plan, estimate, extractChoose the FFprobe executable. The option wins over CHRONA_FFPROBE, the bundled binary, and PATH.
Default: resolvedRepeatable: NoConflicts: No conflict.
Edit and output options
--start TIMEApplies to plan, estimate, extractSet the retained start. TIME accepts seconds, MM:SS, or HH:MM:SS with fractional seconds.
Default: 0 secondsRepeatable: NoConflicts: Must be before the retained end.--end TIMEApplies to plan, estimate, extractSet the retained end. The CLI rejects a value beyond the source duration; range resolution clamps valid trim and cut boundaries to the source.
Default: source durationRepeatable: NoConflicts: Must be after the retained start.--cut START..ENDApplies to plan, estimate, extractRemove a half-open source range. Overlapping or touching cuts are merged, and cuts are clamped to the trim range.
Default: noneRepeatable: YesConflicts: The retained result must contain at least one range.--fps MODEApplies to plan, estimate, extractUse original or source timing, detected, a positive decimal up to 240, or a positive rational such as 30000/1001. Decimal input is converted to a rational; common rates keep their canonical fraction. Fixed output timestamps use FFmpeg's nearest-frame rounding, so frames are dropped or duplicated and never interpolated. VFR input remains variable only with original.
Default: originalRepeatable: NoConflicts: Do not combine with a plan unless you intend to override its FPS mode.--crop auto|none|LEFT:TOP:WIDTH:HEIGHTApplies to plan, estimate, extractauto samples frames at 10%, 50%, and 90% at up to 640px analysis width. A border line must be at least 99% black (each channel <=28) or white (each channel >=227), neutral within 20 levels, and shared by all samples. The crop must be at least 1.5% deep and leave at least 25% of each dimension. Coordinates use displayed pixels.
Default: autoRepeatable: NoConflicts: An exact rectangle must stay inside the displayed resolution.--quality 50..100Applies to plan, estimate, extractAt 100, keep displayed dimensions and lossless RGB PNG pixels. Below 100, output width and height are max(1, round(source dimension * scale)); scale is linearly interpolated through 100/1.00, 92/0.90, 80/0.75, 65/0.50, and 50/0.35. RGB channels are quantized through 256, 64, 32, 16, and 8 levels; output is 8-bit RGB and does not carry alpha. Frame count and timestamps are unchanged.
Default: 100Repeatable: NoConflicts: Values outside 50 through 100 are rejected.--archive zip|directoryApplies to plan, estimate, extractChoose a streaming ZIP or a directory with frames/ and manifest.json.
Default: zipRepeatable: NoConflicts: No conflict.--output PATHApplies to plan, estimate, extractSet the output path. Paths are resolved to absolute paths. The -o alias is supported.
Default: <input>-frames.zip or <input>-framesRepeatable: NoConflicts: Broad paths such as the filesystem root, home directory, and current directory are rejected.
Plan and extraction options
--plan PATHApplies to estimate, extractRead schema v2 JSON, or legacy schema v1 which is upgraded in memory. A plan may contain input; otherwise pass the source video before --plan. In extract, --output, --archive, --quality, --fps, and --crop override plan values.
Default: noneRepeatable: NoConflicts: Do not use --start, --end, or --cut to change an existing plan. Create a new plan instead.--dry-runApplies to extractReturn the resolved output path, expected frame count, plan, and FFmpeg command without writing output files.
Default: offRepeatable: NoConflicts: No conflict.--overwriteApplies to plan, probe, extract, frame, downloadReplace an existing target. Extraction removes the existing target before writing; download uses a temporary .part file and renames after validation.
Default: offRepeatable: NoConflicts: Without it, an existing target is an error.--png-depth 8|16|autoApplies to extractChoose PNG channel depth. auto uses 16-bit for HDR at quality 100 and 8-bit otherwise. Quality below 100 forces 8-bit.
Default: autoRepeatable: NoConflicts: 16-bit output is meaningful only for quality 100.--compression 0..9Applies to extractSet FFmpeg PNG compression effort. It changes encoding work and file size, not pixels or dimensions.
Default: 6Repeatable: NoConflicts: Values outside 0 through 9 are rejected.--keep-tempApplies to extractKeep the OS temporary directory used for frames and manifest debugging. The directory is not removed after success or failure when enabled.
Default: offRepeatable: NoConflicts: No conflict.
Animation analysis
--intent understand|replicate|debugApplies to analyzeRecord the analysis goal in the report.
Default: understandRepeatable: NoConflicts: No conflict.--focus DESCRIPTIONApplies to analyzeRecord a visual concern for downstream inspection.
Default: noneRepeatable: YesConflicts: No conflict.--analysis-width 160..640Applies to analyzeSet the bounded low-resolution scan width.
Default: 480Repeatable: NoConflicts: No conflict.--max-overview-frames 4..16Applies to analyzeSet the overview evidence capacity.
Default: 16Repeatable: NoConflicts: No conflict.--segment IDApplies to inspectInspect one activity segment from analyze.
Default: noneRepeatable: NoConflicts: Pass exactly one of --segment or --frames.--frames NUMBERSApplies to inspectInspect comma-separated analysis frame numbers.
Default: noneRepeatable: NoConflicts: Pass exactly one of --segment or --frames.--region auto|full|region-N|LEFT:TOP:WIDTH:HEIGHTApplies to inspectChoose the full frame, detected attention, a named region, or normalized coordinates.
Default: autoRepeatable: NoConflicts: Coordinates must stay inside the frame.--cache-dir PATHApplies to analyze, inspect, cacheOverride the local analysis cache.
Default: platform cache directoryRepeatable: NoConflicts: No conflict.
Sharing
--app-url URLApplies to shareChoose the Chrona deployment used for the presigned upload and returned artifact URL. HTTPS is required except for localhost.
Default: CHRONA_APP_URL or the deployed siteRepeatable: NoConflicts: No conflict.
Data contracts
The CLI has command-specific success payloads. Errors and progress have shared shapes. Do not assume an undocumented ok or command wrapper.
Successful results
- Put --json before or after the command. Successful stdout is the command payload, not a shared wrapper.
JSON mode never prompts. Human diagnostics and MCP server diagnostics go to stderr.
doctor
{
"ready": true,
"ffmpeg": { "available": true, "path": "...", "version": "6.1.1" },
"ffprobe": { "available": true, "path": "...", "version": "6.1.1" }
}extract
{
"dryRun": false,
"output": "/absolute/path/frames.zip",
"archive": "zip",
"frameCount": 300,
"bytes": 12345678,
"manifestSchemaVersion": 4
}Errors
Failed JSON-mode commands write { error: { message, code, details? } } to stdout and set the same numeric exit code. A missing details field means the error did not carry structured validation issues.
{
"error": {
"message": "Output already exists: /absolute/path/frames.zip. Pass --overwrite to replace it.",
"code": 2
}
}Cancellation has no success payload: the CLI exits 5 with error.code 5, and MCP returns isError true with structuredContent.error.code 5. Extraction removes temporary frames unless --keep-temp is set; a partial final archive can remain after a write failure.
Progress
Use --progress json for JSON Lines on stderr. Each event starts with { type: "progress", stage }. Progress never shares stdout with the machine result.
{"type":"progress","stage":"extracting","frame":418,"total":1842,"outTimeSeconds":13.9139}probingMetadata and frame timing are being read. Frame counts may be absent.extractingframe, total, and outTimeSeconds describe native progress.archivingThe frame set is being written to the selected archive.completeThe extraction task has finished writing.Units and optional fields
- Time
- JSON numbers in seconds. Retained ranges are half-open:
[start, end). - Rate
- A rational object with positive integer
numeratoranddenominator. - Paths
- CLI result paths are absolute after resolution. URLs are strings. Byte counts are integer bytes.
- Optional data
- CLI
probe --fastomitsframes. Errordetailsis omitted when no structured details exist.
Manifest v4
Every completed archive contains a manifest. Frame names are continuous and one-based. The manifest maps each output frame to stitched and source timestamps.
{
"schemaVersion": 4,
"generator": {
"name": "Chrona",
"version": "0.2.0",
"engine": "cli-ffmpeg"
},
"createdAt": "2025-01-01T00:00:00.000Z",
"source": {
"fileName": "video.mp4",
"fileSize": 1048576,
"mimeType": "video/mp4",
"container": "QuickTime / MOV",
"duration": 12.5,
"sourceStart": 0,
"codec": "h264",
"codecString": "h264 High",
"codedWidth": 1920,
"codedHeight": 1080,
"displayWidth": 1920,
"displayHeight": 1080,
"rotation": 0,
"pixelAspectRatio": { "numerator": 1, "denominator": 1 },
"color": { "primaries": "bt709", "transfer": "bt709", "matrix": "bt709", "fullRange": false },
"hdr": false,
"decodable": true,
"frameCount": 375,
"averageFps": 30,
"detectedRate": { "numerator": 30, "denominator": 1 },
"timingMode": "constant"
},
"extraction": {
"fpsMode": { "kind": "fixed", "rate": { "numerator": 30, "denominator": 1 } },
"retainedRanges": [{ "start": 2, "end": 2.033333333 }],
"frameCount": 1,
"sourceCrop": null,
"displayedResolution": { "width": 1920, "height": 1080 },
"outputFormat": "png",
"qualityStatement": "Original displayed resolution, exported as lossless PNG with no additional lossy compression."
},
"frames": [{
"number": 1,
"file": "frames/frame_000001.png",
"stitchedTimestamp": 0,
"requestedSourceTimestamp": 2,
"decodedSourceTimestamp": 2,
"sourceFrameDuration": 0.033333333
}]
}Plan files
Plans are JSON edit decisions. They do not contain video bytes, PNGs, or an intermediate video.
- Plan schema v2 stores retained source ranges, FPS mode, source crop, quality, archive type, and optional source and path fields.
- Ranges are half-open seconds: [start, end). A plan retains at least one range. Fixed FPS is stored as an exact { numerator, denominator } rational.
- Browser-created plans may omit input and output. Pass the local source path before --plan when the plan has no input.
- CLI-generated plans resolve input and output paths on the machine that created them. They are shareable decisions, not machine-independent paths.
- The CLI reads legacy schema v1 plans and upgrades them to schema v2 in memory. Incompatible future plan changes require a new schema version.
{
"schemaVersion": 2,
"source": {
"fileName": "video.mp4",
"fileSize": 1048576,
"duration": 12.5
},
"input": "/absolute/path/video.mp4",
"retainedRanges": [
{ "start": 2, "end": 5 },
{ "start": 7, "end": 12 }
],
"fpsMode": {
"kind": "fixed",
"rate": { "numerator": 30000, "denominator": 1001 }
},
"sourceCrop": null,
"quality": 80,
"archive": "zip"
}Browser to CLI:
npx -y chrona-cli@0.2.0 --json extract ./video.mp4 --plan edit.chrona.json --output frames.zipRun schema plan for the complete JSON Schema. Run --write to save a CLI-created plan.
MCP server and tools
MCP runs over stdio and exposes typed tools for local video paths.
Host configuration
This exact mcpServers object is accepted by Claude Desktop and Cursor. Other hosts may use a different settings key.
{
"mcpServers": {
"chrona": {
"command": "npx",
"args": ["-y", "chrona-cli@0.2.0", "mcp"]
}
}
}- Claude Desktop: put this object in the user
claude_desktop_config.jsonfile undermcpServers. - Cursor: put this object in the user or project
mcp.jsonfile undermcpServers. - Other hosts: use their stdio-server settings. Hosts that use a different key, such as
servers, need a host-specific translation.
- The process uses stdin and stdout for MCP messages.
- Chrona diagnostics go to stderr. Do not parse stderr as tool output.
- Pin
chrona-cli@0.2.0. SetCHRONA_FFMPEG,CHRONA_FFPROBE, orCHRONA_APP_URLin the host environment when needed. - Closing the host connection stops the process. Cancel the request to stop active probe, extraction, share, or download work.
Tool inputs and results
BinaryStatus= { available: boolean, path: string, version: string|null, error?: string }.PlanV2is the schema v2 plan under Plan files.CropChoiceis auto, none, orCropRectangle.CropRectangle= { left: integer, top: integer, width: integer, height: integer }.Resolution= { width: integer, height: integer }.VideoMetadatais the complete metadata object returned by probe: fileName, fileSize, mimeType, container, duration, sourceStart, codec, codecString, codedWidth, codedHeight, displayWidth, displayHeight, rotation, pixelAspectRatio, color, hdr, decodable, frameCount, averageFps, detectedRate, and timingMode.Timeis a nonnegative numeric-seconds value, MM:SS, or HH:MM:SS; fractional seconds are accepted.- Optional fields use
?. Defaults use=. JSON numbers are integers where marked and seconds for times unless stated otherwise.
doctor
CLI: doctorInputs: { ffmpegPath?: string, ffprobePath?: string }
Result: { ready: boolean, ffmpeg: BinaryStatus, ffprobe: BinaryStatus }
Cancellation: No active media operation.
analyze_animation
CLI: analyzeInputs: { input: string, start?: Time, end?: Time, intent?: understand|replicate|debug, focus?: string[], analysisWidth?: int 160..640, maxOverviewFrames?: int 4..16, cacheDirectory?: string }
Result: AnimationAnalysisV1 plus an embedded overview image
Cancellation: Cancel the request to stop FFprobe, FFmpeg, and rendering.
inspect_animation_segment
CLI: inspect --segmentInputs: { analysisId: string, segmentId: string, sampling?: auto|all|uniform|events, region?: Region, maxFrames?: int 1..24 }
Result: AnimationInspection plus an embedded JPEG sheet
Cancellation: Cancel the request to stop frame decoding and rendering.
inspect_animation_frames
CLI: inspect --framesInputs: { analysisId: string, frameNumbers: int[], region?: Region, presentation?: strip|grid, resolution?: preview|full }
Result: AnimationInspection plus an embedded PNG sheet
Cancellation: Cancel the request to stop frame decoding and rendering.
probe_video
CLI: probeInputs: { input: string, includeFrames?: boolean = true, detectCrop?: boolean = true, ffmpegPath?: string, ffprobePath?: string }
Result: { metadata: VideoMetadata, frames: FrameBoundary[], pixelFormat: string|null, autoCrop: CropRectangle|null }
Cancellation: The request signal is passed to native probing.
create_plan
CLI: planInputs: { input: string, start?: Time, end?: Time, cuts?: string[], fps?: string, crop?: CropChoice = auto, quality?: int 50..100 = 100, archive?: zip or directory = zip, output?: string, ffmpegPath?: string, ffprobePath?: string }
Result: { plan: PlanV2, estimatedFrames: integer }
Cancellation: The request signal is passed to probing.
estimate_output
CLI: estimateInputs: { plan: PlanV2, input?: string, ffmpegPath?: string, ffprobePath?: string }
Result: { frameCount: integer, estimatedBytes: integer, averageFrameBytes: integer, sampleCount: integer, quality: integer, displayedResolution: Resolution }
Cancellation: The request signal is passed to probing and sampling.
extract_frames
CLI: extractInputs: { plan: PlanV2, input?: string, overwrite?: boolean = false, dryRun?: boolean = false, pngDepth?: 8, 16, or auto = auto, compression?: int 0..9 = 6, ffmpegPath?: string, ffprobePath?: string }
Result: Dry run: { dryRun: true, output, rootName, expectedFrames, plan, command }. Success: { dryRun: false, output, archive, frameCount, bytes, manifest }
Cancellation: Cancel the request. Native extraction receives the signal; temporary frames are cleaned.
validate_output
CLI: validateInputs: { output: string }
Result: { valid: true, type: zip or directory, path: string, frameCount: integer, schemaVersion: 4 }
Cancellation: No active media operation.
read_frame
CLI: frameInputs: { output: string, frameNumber: positive integer, write?: string, overwrite?: boolean = false }
Result: { output: string, frameNumber: integer, bytes: integer, width: integer, height: integer }
Cancellation: Not cancellable through the current tool adapter.
download_archive
CLI: downloadInputs: { url: URL, output?: string, overwrite?: boolean = false }
Result: { output: string, bytes: integer, frameCount: integer }
Cancellation: Cancel the request to abort the download; partial files are removed.
extract_frames input
{
"plan": {
"schemaVersion": 2,
"input": "/absolute/path/video.mp4",
"retainedRanges": [{ "start": 0, "end": 12 }],
"fpsMode": { "kind": "fixed", "rate": { "numerator": 30, "denominator": 1 } },
"sourceCrop": null,
"quality": 100,
"archive": "zip"
},
"overwrite": false,
"dryRun": false,
"pngDepth": "auto",
"compression": 6
}extract_frames structured result
{
"dryRun": false,
"output": "/absolute/path/video-frames.zip",
"archive": "zip",
"frameCount": 360,
"bytes": 12345678,
"manifest": { "schemaVersion": 4, "extraction": { "frameCount": 360 } }
}MCP failures set isError: true, return the human message as text content, and expose structuredContent.error with the same numeric code used by the CLI.
Troubleshooting and exit codes
Use the JSON error code to choose a recovery path. The message explains the immediate failure; the table explains whether a retry can help.
0Success
No error object
RetryNo
RecoveryContinue with the result.
2Invalid arguments or command
error.code is 2
RetryNo
RecoveryFix the command, choice, path, or range, then rerun.
3Native dependency unavailable
error.code is 3
RetryAfter fixing the binary
RecoveryReinstall, pass explicit paths, or put runnable binaries on PATH.
4Invalid or unsupported input
error.code is 4
RetryAfter changing the input
RecoveryUse a readable local file and a supported codec or correct the plan source.
5FFmpeg, extraction, or cancellation failure
error.code is 5
RetrySometimes
RecoveryCheck the native diagnostic, retry after correcting the source or settings, or rerun after cancellation.
6Output validation failure
error.code is 6
RetryAfter removing or repairing output
RecoveryRun validate, inspect the manifest and first PNG, then regenerate if needed.
7Share or download network failure
error.code is 7
RetryYes, for transient network errors
RecoveryCheck the URL, deployment, expiration, and network, then retry.
Binary resolution
Run doctor --json first. Compare the reported paths and versions with the expected machine. Explicit flags are the highest-precedence override.
Cleanup
Extraction uses an OS temporary directory named chrona-*. It is removed after a normal run unless --keep-temp is set. Download uses a .part-* file and removes it after failure.
Share links
A link is an access credential until its 24-hour deadline. Treat it as sensitive, do not log it in public output, and use download before it expires.
Shared artifact links
A shared Chrona link is readable over HTTP without the CLI. Every route answers JSON, an image, or the file itself.
- Every artifact page links these routes directly, so an agent that cannot follow a path it built itself can follow the page's own links instead.
GET /artifacts/<token>/manifest.jsonis the entry point. It reports the kind, size, expiry, both download routes, and for an archive the frame index. Every URL it returns is absolute./artifacts/<token>/framesis an HTML index of the same frames, one ordinary link per frame, for clients that read pages rather than JSON.GET /artifacts/<token>/downloadredirects to storage on another host, which keeps large transfers off Chrona. Add?direct=1to have Chrona stream the bytes from this origin instead.- Use
?direct=1when the client cannot follow a redirect to a second hostname. It supportsHEADandRange, so an agent can size a transfer and resume one. GET /artifacts/<token>/frames/<name>returns one PNG from an archive underimage/png, so a frame can be inspected without downloading or unpacking the ZIP.- Frame listings page with
?offset=and?limit=. Follow thenextfield until it is null. - A link lasts 24 hours. An expired link answers 410 and an unknown one answers 404, both as text or JSON rather than an HTML page.
Versioning and licensing
Pin the package for automation. Read the schemas from the command that will consume them.
Release notes
- Pin chrona-cli@0.2.0 in scripts and MCP settings. Update the pin intentionally.
- Plan schema v2 and manifest schema v4 are the current compatibility boundaries.
- An incompatible manifest change requires a new schemaVersion. Optional metadata can remain within v4 only when existing meaning stays unchanged and tests cover it.
- The FFmpeg and FFprobe packages include GPL-3.0-or-later license files. Keep those files when redistributing the binaries.