Skip to main content

Chrona CLI and MCP

Analyze animation evidence or extract PNG frames from a local video with the CLI or MCP.

Source videos stay local. Only share uploads the completed ZIP.

Quick start

Example
npx -y chrona-cli@0.2.0 --json doctor

Expected result shape

Copy JSON example
{
  "ready": true,
  "ffmpeg": { "available": true, "path": "...", "version": "6.1.1" },
  "ffprobe": { "available": true, "path": "...", "version": "6.1.1" }
}

Prerequisites

  • Requires Node.js 22 or later.
  • Bundled binaries target macOS x64 and arm64, Linux x64, ia32, arm64, and arm, and Windows x64 and ia32.
  • Container and codec support follows the FFmpeg build that runs on the machine. Chrona commonly identifies MP4, MOV, WebM, and Matroska inputs; an unknown extension is still passed to FFprobe.
  • Resolution order is the explicit path option, the CHRONA_FFMPEG or CHRONA_FFPROBE environment variable, the bundled binary, then ffmpeg or ffprobe on PATH.
  • If npm skips install scripts or the platform is not bundled, pass --ffmpeg-path and --ffprobe-path or install compatible binaries on PATH.
  • The bundled FFmpeg and FFprobe packages include GPL-3.0-or-later license files.

Pinned release

Use chrona-cli@0.2.0 in scripts and host settings. The browser app does not need the npm package.

Read versioning rules
On this page

CLI or MCP?

Use the CLI for scripts and CI, or use MCP for typed calls from an agent host.

Scripts, shells, and CICLIDirect process control with exit codes.
Typed calls from an agent hostMCPStdio tools with structured content.
Understand or reproduce animationanalyzeAdaptive evidence with exact source timestamps.
Move edits between browser and native runsPlan fileVersioned JSON with retained ranges and output settings.
Send a completed archiveshareUploads 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.

Example
npx -y chrona-cli@0.2.0 --json probe ./video.mp4
Probe reference

Extract a range with a cut

Retain 00:02 through 00:12, remove 00:05 through 00:07, and write a ZIP.

Example
npx -y chrona-cli@0.2.0 --json extract ./video.mp4 \
  --start 00:02 \
  --end 00:12 \
  --cut 00:05..00:07 \
  --output frames.zip
Extract reference

Save the edit, then reuse it

A plan stores decisions, not frames. Run it again with the same source or pass a new output path.

Example
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.zip
Plan file reference

Share a completed archive

Validate locally, then upload only the finished ZIP. Links expire after 24 hours.

Example
npx -y chrona-cli@0.2.0 --json share ./frames.zip
Share reference

Browser 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.

Example
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.

Example
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.

Example
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.

Example
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.

Example
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.

Example
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.

Example
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.

Example
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.

Example
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.

Example
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.

share

Validate a finished ZIP, upload it, and create a 24-hour link.

Example
npx -y chrona-cli@0.2.0 --json --progress json share ./frames.zip
  • Only a validated Chrona ZIP is uploaded. The source video is not an input to this command.
  • The archive limit is 4 GB. The result has url, archiveName, archiveBytes, and expiresAt, where expiresAt is an epoch-millisecond number.
  • Use --app-url or CHRONA_APP_URL to target another Chrona deployment. Share URLs contain an encrypted artifact token and are sensitive until expiration.
Result shape
{ url: string, archiveName: string, archiveBytes: integer, expiresAt: number }
Recovery
Fix validation or the archive size locally. Retry network failures. The resumable upload can continue from the server-reported byte offset.

download

Download a shared archive, then validate it before returning success.

Example
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.

Example
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.

Example
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 commands

Write 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, share

Write progress to stderr. json emits one JSON object per line; none suppresses progress.

Default: ttyRepeatable: NoConflicts: No conflict.
--quietApplies to All CLI commands

Suppress 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, extract

Choose 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, extract

Choose 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, extract

Set 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, extract

Set 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, extract

Remove 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, extract

Use 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, extract

auto 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, extract

At 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, extract

Choose a streaming ZIP or a directory with frames/ and manifest.json.

Default: zipRepeatable: NoConflicts: No conflict.
--output PATHApplies to plan, estimate, extract

Set 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, extract

Read 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 extract

Return 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, download

Replace 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 extract

Choose 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 extract

Set 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 extract

Keep 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 analyze

Record the analysis goal in the report.

Default: understandRepeatable: NoConflicts: No conflict.
--focus DESCRIPTIONApplies to analyze

Record a visual concern for downstream inspection.

Default: noneRepeatable: YesConflicts: No conflict.
--analysis-width 160..640Applies to analyze

Set the bounded low-resolution scan width.

Default: 480Repeatable: NoConflicts: No conflict.
--max-overview-frames 4..16Applies to analyze

Set the overview evidence capacity.

Default: 16Repeatable: NoConflicts: No conflict.
--segment IDApplies to inspect

Inspect one activity segment from analyze.

Default: noneRepeatable: NoConflicts: Pass exactly one of --segment or --frames.
--frames NUMBERSApplies to inspect

Inspect 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 inspect

Choose 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, cache

Override the local analysis cache.

Default: platform cache directoryRepeatable: NoConflicts: No conflict.

Sharing

--app-url URLApplies to share

Choose 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

Copy JSON example
{
  "ready": true,
  "ffmpeg": { "available": true, "path": "...", "version": "6.1.1" },
  "ffprobe": { "available": true, "path": "...", "version": "6.1.1" }
}

extract

Copy JSON example
{
  "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.

Copy JSON example
{
  "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.

Copy JSONL example
{"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 numerator and denominator.
Paths
CLI result paths are absolute after resolution. URLs are strings. Byte counts are integer bytes.
Optional data
CLI probe --fast omits frames. Error details is 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.

Copy manifest example
{
  "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
  }]
}
Use validate to check an archive

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.
Copy plan example
{
  "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:

Example
npx -y chrona-cli@0.2.0 --json extract ./video.mp4 --plan edit.chrona.json --output frames.zip

Run 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.

Copy MCP settings
{
  "mcpServers": {
    "chrona": {
      "command": "npx",
      "args": ["-y", "chrona-cli@0.2.0", "mcp"]
    }
  }
}
  • Claude Desktop: put this object in the user claude_desktop_config.json file under mcpServers.
  • Cursor: put this object in the user or project mcp.json file under mcpServers.
  • 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. Set CHRONA_FFMPEG, CHRONA_FFPROBE, or CHRONA_APP_URL in 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 }.
  • PlanV2 is the schema v2 plan under Plan files. CropChoice is auto, none, or CropRectangle. CropRectangle = { left: integer, top: integer, width: integer, height: integer }. Resolution = { width: integer, height: integer }.
  • VideoMetadata is 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.
  • Time is 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.

Inputs: { ffmpegPath?: string, ffprobePath?: string }

Result: { ready: boolean, ffmpeg: BinaryStatus, ffprobe: BinaryStatus }

Cancellation: No active media operation.

analyze_animation

CLI: analyze

Inputs: { 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 --segment

Inputs: { 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 --frames

Inputs: { 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: probe

Inputs: { 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: plan

Inputs: { 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: estimate

Inputs: { 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: extract

Inputs: { 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: validate

Inputs: { output: string }

Result: { valid: true, type: zip or directory, path: string, frameCount: integer, schemaVersion: 4 }

Cancellation: No active media operation.

read_frame

CLI: frame

Inputs: { 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.

share_archive

CLI: share

Inputs: { archive: string, appUrl?: HTTPS URL }

Result: { url: string, archiveName: string, archiveBytes: integer, expiresAt: epoch milliseconds }

Cancellation: Cancel the request to abort validation or upload.

download_archive

CLI: download

Inputs: { 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

Copy MCP 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

Copy MCP 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.

0

Success

No error object

RetryNo

RecoveryContinue with the result.

2

Invalid arguments or command

error.code is 2

RetryNo

RecoveryFix the command, choice, path, or range, then rerun.

3

Native dependency unavailable

error.code is 3

RetryAfter fixing the binary

RecoveryReinstall, pass explicit paths, or put runnable binaries on PATH.

4

Invalid 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.

5

FFmpeg, extraction, or cancellation failure

error.code is 5

RetrySometimes

RecoveryCheck the native diagnostic, retry after correcting the source or settings, or rerun after cancellation.

6

Output validation failure

error.code is 6

RetryAfter removing or repairing output

RecoveryRun validate, inspect the manifest and first PNG, then regenerate if needed.

7

Share 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.json is 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>/frames is an HTML index of the same frames, one ordinary link per frame, for clients that read pages rather than JSON.
  • GET /artifacts/<token>/download redirects to storage on another host, which keeps large transfers off Chrona. Add ?direct=1 to have Chrona stream the bytes from this origin instead.
  • Use ?direct=1 when the client cannot follow a redirect to a second hostname. It supports HEAD and Range, so an agent can size a transfer and resume one.
  • GET /artifacts/<token>/frames/<name> returns one PNG from an archive under image/png, so a frame can be inspected without downloading or unpacking the ZIP.
  • Frame listings page with ?offset= and ?limit=. Follow the next field 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.