difyctl get applists your appsdescribe appshows one app’s details and inputsrun appinvokes oneresume appcontinues a workflow that paused for human inputexport studio-app/import studio-appexports / imports apps as DSL files
List Your Apps
Arguments
[app-id]: optional. The ID of one app to show. Omit it to all apps.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--name <substring> | string | none | Filter to apps whose name contains this text. |
--mode <mode> | string | none | Filter by app type, named by its API mode:
|
--page <n> | integer | 1 | Page number. |
--limit <n> | integer | 20 | Page size, 1 to 200. The flag wins, then DIFY_LIMIT. |
--workspace <id> | string | active workspace | Run against another workspace for this invocation only. For how difyctl resolves the workspace, see How difyctl Picks a Workspace. |
-A, --all-workspaces | boolean | false | List apps across every workspace your token can see. |
-o <format> | string | none | Output format: json, yaml, name, or wide. Omit the flag for the default table. |
External SSO users see the apps an administrator permitted, not a workspace listing;
--workspace and -A don’t apply. See Scope and Limitations for details.Examples
List the apps in your workspace:Output
| Format | What stdout gets |
|---|---|
| default | An aligned table. The MODE column is each app’s API mode name (see --mode for the mapping to app types). |
-o wide | The table plus a WORKSPACE column. |
-o json, -o yaml | A data array of the apps, plus the paging fields page (current page), limit (page size), total (apps matched), and has_more (whether more pages remain). |
-o name | The app IDs, one per line. |
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Network or server error |
2 | Usage error, such as a --limit outside 1 to 200 |
4 | Authentication failure |
7 | Rate limited (HTTP 429) |
Inspect an App
describe app answers the question you have before running an unfamiliar app: what type of app is it, is its API enabled, and what inputs does it expect.
Arguments
<app-id>: required. The ID of the app to inspect.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--refresh | boolean | false | Bypass the local app-info cache and fetch fresh details. Use after an app was republished. |
-o <format> | string | text | Output format: json, yaml, or text. |
Examples
Inspect an app before running it:--inputs programmatically:
Output
| Format | What stdout gets |
|---|---|
default (text) | An aligned field block, then the app’s parameters (including the user input form). |
-o json, -o yaml | Three top-level keys: info, parameters, and input_schema (detailed below). |
Description: row appears when the app has one, and an Agent: true row when the app is agentic.
Under -o json, the three keys are:
info- the metadata fields shown above, fromNametoService APIparameters- the parameters block shown aboveinput_schema- a normalized list of the app’s inputs, the field thejq '.input_schema'example reads
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Network or server error, including app not found |
2 | Usage error, including a non-UUID <app-id> |
4 | Authentication failure |
7 | Rate limited (HTTP 429) |
Run an App
run app is one command for all app types. The CLI reads the app’s type and dispatches to the right endpoint. What changes is how you pass input and the response shape:
- Chatbot, Chatflow, Agent: take a positional message, print the reply to stdout, and print a conversation hint to stderr.
- Text Generator: takes a positional message and prints the completion to stdout. No conversational state, no hint.
- Workflow: takes a JSON object via
--inputsand prints its outputs to stdout. A workflow whose output is a single string prints it raw. Anything else prints as compact JSON.
Arguments
<app-id>: required. The ID of the app to run, fromget app.[message]: the user message, for Chatbot, Chatflow, Agent, and Text Generator apps. Workflow apps reject a positional message, so pass their inputs with--inputs.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--inputs <json> | string | none | Input variables as one JSON object, e.g. --inputs '{"topic":"Q3"}'. Required for Workflow apps. Mutually exclusive with --inputs-file. |
--inputs-file <path> | string | none | Read the inputs object from a JSON file instead. |
--file <key=value> | string, repeatable | none | Named file input. key=@path uploads a local file. key=https://… passes a remote URL without uploading. The key is the input variable name. |
--conversation <id> | string | none | Continue an existing conversation. The ID comes from the stderr hint or the JSON response of an earlier run. |
--workflow-id <id> | string | none | Pin the run to a specific published workflow version. Workflow and Chatflow apps only. |
--stream | boolean | false | Print the output live as it’s generated, instead of all at once at the end. |
--think | boolean | false | Print the model’s thinking to stderr when the model exposes it. Without this flag, <think> blocks are stripped silently. |
--retry-on-limit | boolean | false | On a 429 rate limit, wait and retry the run instead of failing with exit 7. Off by default, since a run isn’t idempotent. |
--workspace <id> | string | active workspace | Run against another workspace for this invocation only. For how difyctl resolves the workspace, see How difyctl Picks a Workspace. |
-o <format> | string | text | Output format: json, yaml, or text. |
Examples
Send a message to a Chatbot, Chatflow, Agent, or Text Generator app:Output
| Format | What stdout gets |
|---|---|
default (text) | The reply (Chatbot, Chatflow, Agent, Text Generator) or the workflow’s output, as plain text. |
-o json, -o yaml | The full server payload, including answer and conversation_id for conversational apps, plus the model’s reasoning under metadata.reasoning when present. |
--stream, output prints incrementally as the server produces it. If a run fails with HTTP 422 right after an app was republished, the CLI clears its app-metadata cache and hints to run the command again.
Errors print to stderr. Under -o json they arrive as a structured JSON object with a stable code field. See Output Formats and Exit Codes for the error shape.
Exit Codes
| Code | Meaning |
|---|---|
0 | Success, including a workflow that paused for human input |
1 | Network or server error, including app not found |
2 | Usage error: invalid --inputs JSON, or a positional message passed to a Workflow app |
4 | Authentication failure |
7 | Rate limited (HTTP 429) |
When a Workflow Pauses
Workflow apps can include human-input steps. When a run reaches one, it pauses instead of finishing: the command exits 0 (a pause is not a failure), prints the pause to stdout, and prints a ready-to-run resume command to stderr:-o json, stdout gets the pause as a JSON object instead:
-o json and check stdout for "status": "paused". Three fields drive the resume: form_token, workflow_run_id, and (when the form offers more than one action) the action id. Forms expire at expiration_time (Unix epoch seconds).
When the workflow delivers its form through email or another external channel, form_token is null and the run can’t be resumed from the CLI.
Resume a Paused Workflow
resume app submits the form a paused workflow is waiting on, then attaches to the run and prints its output exactly like run app.
Arguments
<app-id>: required. Theapp_idfrom the pause payload.<form-token>: required. Theform_tokenfrom the pause payload. Tokens are single-use, so resuming with an already-consumed token returns an error.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--workflow-run-id <id> | string | required | The workflow_run_id from the pause payload. |
--action <id> | string | auto-selected | Which form action to take, by id from the pause payload’s actions.Optional when the form has exactly one action, required when it has several. |
--inputs <json> | string | none | Values for the form’s inputs as one JSON object, keyed by each input’s output_variable_name.Mutually exclusive with --inputs-file. |
--inputs-file <path> | string | none | Read the form values from a JSON file instead. |
--with-history | boolean | false | Replay the output of already-executed nodes before attaching to the live stream. |
--stream | boolean | false | Print the output live as it’s generated, instead of all at once at the end. |
--think | boolean | false | Print the model’s thinking to stderr when the model exposes it. Without this flag, <think> blocks are stripped silently. |
-o <format> | string | text | Output format: json, yaml, or text. |
Examples
Approve a single-action form, providing its input values:Output
| Format | What stdout gets |
|---|---|
default (text) | The workflow’s output as the run completes. stderr confirms the submission and the finish. |
-o json, -o yaml | The run result as one document, just like run app (a pause payload if it pauses again). |
Exit Codes
| Code | Meaning |
|---|---|
0 | Success, including the run pausing again at a later node |
1 | Error, including a consumed form token, or omitting --action on a form with several actions |
2 | Usage error |
4 | Authentication failure |
7 | Rate limited (HTTP 429) |
Export an App
export studio-app writes the app’s full definition as a DSL YAML document, for versioning, backup, or importing elsewhere.
For Workflow and Chatflow apps, export returns the current draft, not the published version that run app executes. Use --workflow-id to export a specific published version instead. Chatbot, Agent, and Text Generator apps export the published version.
Arguments
<app-id>: required. The ID of the app to export, fromget app.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
-o, --output <path> | string | none | Write the DSL to this file instead of stdout. On this command, -o is the output file path, not the output-format selector. |
--include-secret | boolean | false | Include encrypted secret values in the exported DSL. |
--workflow-id <id> | string | none | Export a specific published workflow version by ID, instead of the default draft. Workflow and Chatflow apps only. |
--workspace <id> | string | active workspace | Run against another workspace for this invocation only. For how difyctl resolves the workspace, see How difyctl Picks a Workspace. |
Examples
Print an app’s DSL to stdout:Output
The DSL YAML document prints to stdout: akind: app header, a version field, and the full app definition. With --output, the same content is written to the file and stderr confirms it:
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Network or server error, including app not found |
2 | Usage error, including a missing <app-id> |
4 | Authentication failure |
7 | Rate limited (HTTP 429) |
Import an App
import studio-app creates an app from a DSL YAML document, or overwrites an existing one with --app-id.
For Workflow and Chatflow apps, it writes the definition to the app’s draft. run app uses the published version, so publish the app in Dify after importing for the change to take effect.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
-f, --from-file <path> | string | none | Import DSL from a local file. Exactly one of --from-file or --from-url is required. |
--from-url <url> | string | none | Import DSL from an HTTP(S) URL. |
--name <name> | string | from DSL | Override the app name. |
--description <text> | string | from DSL | Override the app description. |
--app-id <id> | string | none | Overwrite an existing app instead of creating a new one. Workflow and Chatflow apps only. |
--workspace <id> | string | active workspace | Import into another workspace for this invocation only. For how difyctl resolves the workspace, see How difyctl Picks a Workspace. |
--icon-type <type> | string | from DSL | Override the icon type. |
--icon <icon> | string | from DSL | Override the icon. |
--icon-background <color> | string | from DSL | Override the icon background color. |
Examples
Import an app from a local DSL file:Output
All status lines go to stderr; stdout stays empty. On success, stderr reports the new app’s ID:Missing plugin dependencies after the import. Install them before using the app.
Exit Codes
| Code | Meaning |
|---|---|
0 | Success, including imports with warnings |
1 | Error, including a missing or conflicting --from-file/--from-url, or a failed import |
2 | Usage error, including a --from-file path that doesn’t exist |
4 | Authentication failure |
7 | Rate limited (HTTP 429) |