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.
--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
Runmulerun 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, …) |
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 |
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) |
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. |
--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://..."]' |
--json):
videos, images, audios) matches the Result Key
field shown by studio params.
Local image inputs
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 |
/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 |
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 |
--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:
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:--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:Scripting
Every studio command supports--json. Pair with jq for clean shell
pipelines:
--quiet to suppress progress while keeping real errors.
Exit codes
| Code | Meaning |
|---|---|
0 | Task completed successfully |
1 | Validation, configuration, network, or terminal task failure |
$? 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 studioinvocation downloads the studio engine into~/.mulerun/vendor/; subsequent calls reuse it. - For fast endpoints (text-to-image), shrinking
--poll-interval 5makes the experience feel snappier. - For very long videos, bump
--max-wait 1800or3600. The task does not get cancelled when the poller stops —statuscan pick it back up. --debugprints the resolved engine path and the exact arguments forwarded to it; handy when an option doesn’t seem to take effect.