Skip to Content
Build with GavanaCLI Reference

CLI Reference

Running the CLI

# After the current source install, or after the future npm release gavana --help

gavana-canvas is the descriptive alias. craftboard and craftboard-canvas remain backward-compatible aliases for existing scripts. See Install the CLI for the current package release status.

Output format

The CLI writes one JSON result to stdout by default:

{ "ok": true, "result": {} }

Errors and progress events go to stderr, so a script or AI client can parse stdout cleanly. Use --output markdown for a chat-ready result or --output jsonl for one selected array item per line.

Use --jq to select a property path and -r to print strings or numbers without JSON quotes:

gavana canvas list --limit 25 --jq '.canvases[].handle' -r gavana asset list --jq '.assets[]' --output jsonl

The built-in selector supports property paths, non-negative array indexes, and [] projections, such as .canvases[0].title or .connections[].models[]. It intentionally does not execute arbitrary jq programs, so it works without a separate jq installation.

Errors include a stable code and, when possible, the exact fields to fix:

{ "ok": false, "error": { "code": "input_validation_error", "message": "baseRevision is required.", "fields": [ { "field": "baseRevision", "message": "Read the canvas and pass its current revision." } ], "requestId": "7f8e0d9d-4bf8-4e6e-96e0-8bcd6a8f315a" } }

The requestId is safe to share with support. Never share an Agent Access Token. Fix validation and permission errors before retrying. A client may retry safe read requests after a temporary error such as rate_limited, service_unavailable, or upstream_timeout; for an image, workflow, video, or other potentially paid write, ask for explicit approval before starting a new attempt.

Exit codes

ExitMeaning
0Success
2Usage, configuration, or validation error
3Authentication or authorization error
4Revision conflict
5Not found
7Network error
8Wait timeout — the Run can still be resumed
9Recipe, image, or Action Run ended unsuccessfully

Core commands

auth login|status|logout config list|use mcp install|config canvas list|create|agent|get|render|apply node get|create|update|move|resize|delete connection list|create|delete asset list|get|upload provider list model list|get recipe search|get|fork|run action list|get|run image generate|edit|variations video generate|download run get|wait|cancel job get|wait|cancel
  • Destructive commands require --yes.
  • Recipe, image, and Action commands wait for durable persistence by default — pass --no-wait to get the shared run: handle immediately and resume it later with run wait.
  • Default waiting plus run get|wait|cancel requires the token’s job:manage scope. A start-only token can use --no-wait and a signed webhook instead.
  • job get|wait|cancel remains an image and Action compatibility alias; it is never used for Recipe Runs.
  • Canvas, Recipe, asset, Action, model, and provider list commands accept --limit and the opaque --cursor returned as page.nextCursor. Keep the same filters when requesting the next page.

Run results include estimatedSeconds, observed queue/execution timing, and a stable failure.code plus failure.retryable when generation fails. A failed provider request is returned as a terminal Run result, so run wait finishes without hiding the reason behind a generic request error. The complete terminal resource remains on stdout for automation, while recipe run, image ..., action run, and run wait return exit code 9 when the terminal state is failed, canceled, or expired.

Image and Action run: handles and their legacy job: aliases address the same temporary record and expire together. By default, unacknowledged results expire after 24 hours; a successfully finalized result expires 15 minutes after its first server finalization (from a Run GET or signed callback), and the expired tombstone is deleted after seven days. Operators may override these windows. Recipe Run records currently do not use this temporary TTL. Persist the returned asset: and node: handles, which remain durable after the observation handles expire.

To receive one signed callback instead of polling, keep the secret out of shell history:

read -rs 'GAVANA_WEBHOOK_SECRET?Webhook signing secret: '; printf '\n' export GAVANA_WEBHOOK_SECRET gavana image generate \ --destination agent-canvas \ --prompt "A studio product photograph" \ --webhook-url "https://automation.example.com/hooks/gavana" \ --no-wait unset GAVANA_WEBHOOK_SECRET

Use --webhook-secret-env MY_SECRET_VARIABLE to read a different environment variable. The CLI sends the secret only in the authenticated Run-start body; Gavana encrypts it and Run output reports only delivery state. Recipe and Image Action starts accept the same webhook options. The always-on worker keeps an authenticated Recipe moving after the original CLI process exits. Successful Image and Action callbacks are sent only after their durable canvas, node, and asset results are stored. Failed, canceled, or expired callbacks describe the terminal state without requiring images.

Stable handles

Use handles returned by Gavana:

canvas:<ownerUid>:<canvasId> node:<nodeId> connection:<connectionId> asset:<assetId> asset:<ownerUid>:<assetId> (shared asset) recipe:<recipeId> action:<slug> model:<opaqueModelKey> run:<runId> job:<jobId>

Use the owner-qualified handle returned by asset list for a shared asset. This lets Gavana read that exact asset directly without searching another user’s library. Recipe and Action handles come from their catalogs. Model, Run, and job IDs are opaque results: copy their complete returned handles and do not decode, guess, or construct them.

Recipe Runs

Forking and running are deliberately separate. recipe fork adds a private, editable Recipe card and never executes it. recipe run is the explicit action that binds typed inputs, creates declared output nodes, and starts text or image work:

gavana recipe run recipe:product-visual-direction \ --input product-context="A matte black travel bottle for a quiet premium campaign" \ --destination canvas:OWNER_UID:CANVAS_ID

Use each exact input key returned by recipe get. Written ports accept inline text, @path, a text/sticky node:, or an image reference when the Recipe asks for “an image or written note.” For that flexible written port, upload a local visual first and pass the returned asset: handle; @path reads the file as text. Image ports accept node: or asset: handles, local raster paths, stdin, or the macOS clipboard. All Recipe starts currently require image:generate and its dependent scopes, including text-only Recipes. The terminal Run returns typed outputs with durable node: and, for images, asset: handles.

Use gavana model list --capability image.edit before choosing a model. The result tells you which saved connection can run it, the exact valid parameters, and its estimated duration. Then inspect one entry with gavana model get model:<opaqueModelKey> and pass the same handle to an image command with --model model:<opaqueModelKey>.

Deterministic Image Actions

Image Actions make precise raster changes without asking an AI model and without spending AI credits. The first stable set is resize, crop, change aspect ratio, side-by-side composite, add text, overlay image, color grade, and rotate.

Inspect the catalog before running an Action:

gavana action list gavana action get action:resize gavana action run action:resize \ --input ./product.png \ --destination agent-canvas \ --width 1080 \ --height 1350

For two-input Actions, repeat --input in the order shown by action get:

gavana action run action:side-by-side-composite \ --input node:FIRST_IMAGE \ --input asset:SECOND_IMAGE \ --destination canvas:OWNER_UID:CANVAS_ID \ --direction horizontal \ --gap 24

Inputs may be node: or asset: handles, a local PNG/JPEG/WebP/GIF path, stdin (-), or clipboard on macOS. The CLI privately uploads local inputs, creates one output node when --target is omitted, waits for durable asset and node handles by default, and returns exit code 9 for a failed terminal Run. Use repeatable --param NAME=VALUE for schema fields that do not have a dedicated flag. Existing handles need only the Action scopes; local, stdin, and clipboard inputs additionally require image:generate for the private upload.

Video generation

Video generation is an explicit potentially paid action. Discover the exact connected model and capability before starting; do not guess a model: handle or retry a failed paid request automatically.

gavana model list --capability video.generate gavana model get model:OPAQUE_MODEL_KEY gavana video generate \ --model model:OPAQUE_MODEL_KEY \ --prompt "A slow product turntable" \ --duration 15 \ --aspect-ratio 9:16 \ --download ./turntable.mp4

For image-to-video, use --first-frame with a durable node:/asset: handle, public HTTPS URL, local image, stdin, or the macOS clipboard. A last frame requires a first frame. Add --no-wait to return the job: handle immediately, then use job get, job wait, job cancel, or video download job:JOB_ID --file ./result.mp4. Generation requires canvas:read, asset:read, and video:generate; waiting, downloading, and cancellation also need job:manage.

Concurrency

An operation that changes an existing canvas takes its latest baseRevision (from a prior read) and an idempotencyKey, so retries are safe and concurrent browser and agent edits do not clobber each other. Creating a new canvas or resolving the persistent Agent Canvas is a separate operation; use the exact contract for that command.

Last updated on