Documentation Index
Fetch the complete documentation index at: https://mulerun.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
mulerun studio is the multimodal generation surface of the CLI. It bundles
40+ image, video, speech, and music model endpoints behind a single
subcommand — all reachable with your existing MuleRun login, no extra API
key.
mulerun studio list # browse the model catalog
mulerun studio params <endpoint> # inspect a model's parameters
mulerun studio run <endpoint> [--param value …] # generate something
mulerun studio status <api-path> <task-id> # poll an async task
mulerun studio config # show resolved configuration
mulerun studio upgrade # update the studio engine
mulerun studio reset # remove the local install
Every command supports --json for machine-readable output. Long-running
endpoints (video, music) can be submitted with --no-wait and resumed
later via status — useful for CI, batches, or LLM-agent workflows.
Authentication
Run mulerun login once and every studio invocation picks up the cached
credential automatically. The CLI exchanges your OAuth token for a
short-lived per-call key before each request, so no manual API-key
management is required. See Configuration for
non-interactive setups (MULERUN_TOKEN).
mulerun studio --help and mulerun studio <subcommand> --help are safe
to run while logged out — they don’t touch the network.
Endpoint identifier
The <endpoint> argument used by params, run, and the catalog uses
this shape:
| Form | Behavior |
|---|
<provider>/<model> | Auto-resolves the action when the model has exactly one |
<provider>/<model>/<action> | Explicit action — required when a model exposes multiple (generation, edit, …) |
Examples: alibaba/wan2.6-t2v, openai/gpt-image-2/edit,
google/nano-banana-2/generation.
Subcommands
studio list
Browse the catalog. With no flags, every registered endpoint is printed
grouped by provider; with flags, the list is narrowed.
| Option | Description |
|---|
--provider <name> | Filter by provider (e.g. alibaba, google, klingai, midjourney, minimax, openai, bytedance) |
--output-type <type> | Filter by output type (image, video, audio) |
--tag <tag> | Filter by tag, e.g. SOTA |
--providers | Print provider names only — skip the model listing |
--json | Output as JSON |
# Everything
mulerun studio list
# All Google models
mulerun studio list --provider google
# Every video endpoint
mulerun studio list --output-type video
# Only SOTA-tagged endpoints
mulerun studio list --tag SOTA
# Just the provider names
mulerun studio list --providers
# Machine-readable
mulerun studio list --json | jq -r '.models[] | "\(.model_id)/\(.action)"'
Text output groups endpoints by provider and shows the canonical
identifier, a one-line description, output type, and any tags:
[ALIBABA]
----------------------------------------
alibaba/wan2.6-t2v/generation [SOTA]
Wan2.6 Text-to-Video: ...
Output: video
alibaba/wan2.6-i2v/generation [SOTA]
Wan2.6 Image-to-Video: ...
Output: video
studio params <endpoint>
Inspect every parameter an endpoint accepts — name, type, required
flag, default value, and enum choices when applicable.
| Option | Description |
|---|
--json | Output as JSON (useful for codegen or LLM consumption) |
mulerun studio params alibaba/wan2.6-t2v
mulerun studio params google/nano-banana-2/edit
mulerun studio params openai/gpt-image-2/generation --json
Text output:
alibaba/wan2.6-t2v/generation
Wan2.6 Text-to-Video: Generate videos from text prompts with multi-shot,
audio, and resolution control
Parameters:
------------------------------------------------------------
--prompt (required)
Type: string
Text prompt describing the video to generate
--size [default: 1280*720] [choices: 1280*720, 960*960, ...]
Type: string
Video resolution
--duration [default: 5] [choices: 5, 10, 15]
Type: integer
Video duration in seconds
...
API Path: /vendors/alibaba/v1/wan2.6-t2v/generation
Output Type: video
Result Key: videos
The trailing metadata tells you the upstream API path (used by status)
and the JSON key under which result URLs appear (videos, images,
audios).
Parameter naming. Parameters are documented in snake_case (matching
the wire format) and exposed as --kebab-case flags. The CLI converts
between the two automatically.
| Documented name | CLI flag |
|---|
prompt | --prompt |
negative_prompt | --negative-prompt |
aspect_ratio | --aspect-ratio |
first_frame | --first-frame |
studio run <endpoint>
The workhorse. Submits a generation task, polls until it completes, and
prints the result URLs.
| Option | Default | Description |
|---|
--no-wait | — | Submit and return immediately. Use status later. |
--poll-interval <s> | 20 | Polling interval in seconds. |
--max-wait <s> | 900 | Maximum wait before the poller gives up (15 min). The task itself keeps running on the server. |
--quiet | — | Suppress per-poll progress lines on stderr. |
--json | — | Machine-readable result on stdout. |
--extra <KEY=VALUE> | — | Inject an undeclared parameter. Repeatable. |
Model parameters are passed as flags using the kebab-case form. Both
--key value and --key=value syntax are accepted. Values are type-coerced
and enum-validated before any HTTP call is made:
| Type | Accepted CLI value |
|---|
string | Any value |
integer | Parsed with parseInt. Invalid values throw. |
number | Parsed with parseFloat. Invalid values throw. |
boolean | true / false, or the bare flag (e.g. --audio ≡ --audio true) |
array | A JSON array string, e.g. --images '["https://..."]' |
Missing required parameters and empty strings for required string
parameters produce a friendly error before the request is sent.
Recipes:
# Text-to-image
mulerun studio run openai/gpt-image-2/generation \
--prompt "A vector logo of a fox, flat style" \
--size "1024x1024" \
--quality high
# Text-to-image with batch + negative prompt
mulerun studio run alibaba/wan2.6-t2i \
--prompt "Ink-wash painting of a Jiangnan water town" \
--size "1280*1280" \
--n 4 \
--negative-prompt "blurry, low quality"
# Text-to-video with audio
mulerun studio run alibaba/wan2.6-t2v \
--prompt "A golden retriever running on a beach at sunrise" \
--duration 10 \
--audio
# Image-to-video — local file path auto-converted to base64
mulerun studio run alibaba/wan2.6-i2v \
--image ./hero.jpg \
--prompt "Slow cinematic push-in, drifting clouds" \
--duration 5
# Image editing with a mask
mulerun studio run openai/gpt-image-2/edit \
--prompt "Put a bouquet of flowers in their hand" \
--images '["https://example.com/person.jpg"]' \
--mask ./mask.png
# Text-to-speech
mulerun studio run minimax/speech-2.8-hd \
--prompt "Hello from the command line." \
--voice-id "Charming_Lady" \
--emotion happy
# Text-to-music
mulerun studio run minimax/music-2.5 \
--prompt "upbeat synthwave" \
--lyrics-prompt "[verse]\nNeon city\n[chorus]\nWe ride"
Output (text, default):
Creating task at /vendors/alibaba/v1/wan2.6-t2v/generation...
[12s] status: queued
[32s] status: running
[52s] status: succeeded
Task ID: 9d2b8c1a-...
Status: succeeded
Results:
https://cdn.mulerun.com/.../video-0.mp4
Output (--json):
{
"task_id": "9d2b8c1a-...",
"status": "succeeded",
"videos": [
"https://cdn.mulerun.com/.../video-0.mp4"
],
"data": { ... }
}
The result-key (videos, images, audios) matches the Result Key
field shown by studio params.
Any parameter that takes an image (--image, --images, --first-frame,
--last-frame, --mask, --mask-image-url, --ref-images-url,
--reference-images, …) accepts three kinds of values:
| Value | Behavior |
|---|
http://... / https://... URL | Forwarded unchanged |
data:image/...;base64,... URI | Forwarded unchanged |
| Local file path (relative or absolute) | Read, validated, base64-encoded, then sent |
Supported formats: PNG, JPG, JPEG, GIF, BMP, WebP, TIFF, SVG, ICO, HEIC,
HEIF, AVIF. Files are capped at 20 MB; paths inside sensitive
directories (/etc, ~/.ssh, ~/.aws, …) are blocked.
If you pass a path that doesn’t exist, the CLI prints a yellow warning to
stderr and still attempts the request (treating the string as a URL). This
makes typos loud while still allowing intentional pass-through of
URL-shaped strings.
studio status <api-path> <task-id>
Check on an async task submitted with run --no-wait (or via the HTTP
API directly).
| Option | Default | Description |
|---|
--wait | — | Poll until the task completes instead of returning immediately |
--poll-interval <s> | 20 | Polling interval in seconds (with --wait) |
--max-wait <s> | 900 | Maximum wait before the poller gives up |
--quiet | — | Suppress per-poll progress lines |
--json | — | Machine-readable output |
# Snapshot — one request, then exit
mulerun studio status /vendors/alibaba/v1/wan2.6-t2v/generation 9d2b8c1a-...
# Block until done
mulerun studio status /vendors/alibaba/v1/wan2.6-t2v/generation 9d2b8c1a-... --wait
# Faster polling, longer ceiling
mulerun studio status /vendors/alibaba/v1/wan2.6-t2v/generation 9d2b8c1a-... \
--wait --poll-interval 10 --max-wait 1800
The api-path argument is printed by run --no-wait, and also shows up
as api_path in studio list --json and as API Path in
studio params.
Status values:
| Status | Terminal? | Meaning |
|---|
pending, queued | No | Accepted, waiting for a worker |
running, processing | No | A worker is generating the asset |
succeeded, completed | Yes | Result URLs are available |
failed | Yes | An error field explains why |
Snapshot calls (without --wait) only exit non-zero on the explicit
failed state; other statuses simply mean “not done yet.”
studio config
Print the resolved configuration (base URL, request timeout, retry
budget). No network call, no secrets revealed. Run this when you suspect
the wrong host is being contacted.
studio upgrade / studio reset
Wrapper-only commands that operate on the local install of the studio
engine:
mulerun studio upgrade # reinstall the engine at @latest
mulerun studio reset # remove the install — next run reinstalls
upgrade is safe to run on a schedule; reset is the escape hatch when
a stale install is misbehaving.
Async workflow
For long jobs (video, music, high-effort image generation), submit
without waiting and resume polling later:
# Step 1 — submit
SUBMIT=$(mulerun studio run alibaba/wan2.6-t2v \
--prompt "A long cinematic shot over a glacier" \
--duration 15 --no-wait --json)
TASK_ID=$(echo "$SUBMIT" | jq -r '.task_id')
API_PATH=$(echo "$SUBMIT" | jq -r '.api_path')
# Step 2 — wait (separate shell, later in CI, ...)
mulerun studio status "$API_PATH" "$TASK_ID" --wait --json > result.json
# Step 3 — download the assets
jq -r '.results[]' result.json | xargs -n1 curl -sSLO
If the poller in step 2 hits its --max-wait budget, the task itself
keeps running on the server — re-run the same status --wait to resume.
Fan-out / fan-in
Submit many prompts in parallel, then wait on the whole batch:
#!/usr/bin/env bash
set -euo pipefail
prompts=(
"A neon-lit Tokyo street at midnight"
"A misty pine forest at dawn"
"A sandstorm rolling across desert dunes"
)
# Fan out
: > tasks.jsonl
for p in "${prompts[@]}"; do
mulerun studio run alibaba/wan2.6-t2v \
--prompt "$p" --duration 5 --no-wait --json --quiet \
| jq -c --arg p "$p" '{task_id, api_path, prompt: $p}' >> tasks.jsonl
done
# Fan in
while read -r line; do
tid=$(jq -r .task_id <<<"$line")
path=$(jq -r .api_path <<<"$line")
mulerun studio status "$path" "$tid" --wait --quiet --json > "result-$tid.json"
done < tasks.jsonl
Scripting
Every studio command supports --json. Pair with jq for clean shell
pipelines:
# Pick a random SOTA model
mulerun studio list --tag SOTA --json \
| jq -r '.models[] | "\(.model_id)/\(.action)"' \
| shuf -n 1
# Extract the first result URL
URL=$(mulerun studio run openai/gpt-image-2/generation \
--prompt "A sunset" --json --quiet | jq -r '.images[0]')
# Download every generated asset
mulerun studio run alibaba/wan2.6-t2v --prompt "Ocean waves" --json --quiet \
| jq -r '.videos[]' \
| xargs -n1 curl -sSLO
Stdout vs stderr. Stdout carries the JSON / text result and is safe
to pipe. Stderr carries per-poll progress lines, warnings, and real
errors. Use --quiet to suppress progress while keeping real errors.
Exit codes
| Code | Meaning |
|---|
0 | Task completed successfully |
1 | Validation, configuration, network, or terminal task failure |
When scripting against the CLI, always check $? before parsing the JSON
— a failed call may still emit JSON, but the shape will contain an
error field instead of results.
Common errors
| Message | What it means |
|---|
Model endpoint '...' not found. | Spelling / version mismatch. Run studio list and copy the identifier. |
Multiple actions found for '...'. | The model has multiple actions. Use the three-part identifier provider/model/action. |
Missing required parameter(s): --xxx. | Add the listed flags. studio params <endpoint> shows what’s required. |
Invalid value for --xxx: '…'. Valid choices: … | The parameter has an enum. Pick one of the listed values. |
Parameter '...' must be a valid JSON array. | Pass array values as a JSON string: --images '["https://..."]'. |
File '...' is N.NMB, exceeding the 20MB limit | Resize, re-encode, or host the file yourself and pass the URL. |
Access denied: '...' is in a sensitive system/home directory | System dirs (/etc, /proc) and dotfile dirs (~/.ssh, ~/.aws) are blocked by design. |
Tips
- The first
mulerun studio invocation downloads the studio engine into
~/.mulerun/vendor/; subsequent calls reuse it.
- For fast endpoints (text-to-image), shrinking
--poll-interval 5 makes
the experience feel snappier.
- For very long videos, bump
--max-wait 1800 or 3600. The task does
not get cancelled when the poller stops — status can pick it back up.
--debug prints the resolved engine path and the exact arguments
forwarded to it; handy when an option doesn’t seem to take effect.