mirror of
https://github.com/langgenius/dify.git
synced 2026-10-16 15:35:32 +08:00
docs(cli): document error fields, exit codes, form follow-up and local files
Update the difyctl skill (operations, plugins, setup) and the README for the changes above.
This commit is contained in:
+24
-12
@@ -2,6 +2,18 @@
|
||||
|
||||
CLI client for the [Dify] platform. Browser device-flow sign-in, then a server-published catalog of operations you discover and call at run time, each one a command. Results are JSON; help and errors are text on a terminal, JSON in a pipe.
|
||||
|
||||
## Install
|
||||
|
||||
difyctl ships as assets on Dify releases. The installer picks the build from the latest release; set `DIFY_VERSION` to match your Dify server:
|
||||
|
||||
```sh
|
||||
curl -fsSL https://raw.githubusercontent.com/langgenius/dify/main/cli/scripts/install-cli.sh | sh
|
||||
```
|
||||
|
||||
Windows (PowerShell): `irm https://raw.githubusercontent.com/langgenius/dify/main/cli/scripts/install.ps1 | iex`.
|
||||
|
||||
The binary goes to `$HOME/.local/bin` (Windows: `%LOCALAPPDATA%\difyctl\bin`). Every installer accepts `DIFYCTL_INSTALL_DIR` (the bin folder itself) and `DIFYCTL_PREFIX` (the folder above it, so the binary lands in `<prefix>/bin`); `DIFYCTL_INSTALL_DIR` wins when both are set.
|
||||
|
||||
## Install (edge, internal)
|
||||
|
||||
Per-commit `edge` builds are published to Cloudflare R2. The installer script lives in this repo; binaries are fetched from R2 via `DIFYCTL_R2_BASE` (shared internally):
|
||||
@@ -10,15 +22,16 @@ Per-commit `edge` builds are published to Cloudflare R2. The installer script li
|
||||
curl -fsSL https://raw.githubusercontent.com/langgenius/dify/main/cli/scripts/install-r2.sh | DIFYCTL_R2_BASE=<BASE> sh
|
||||
```
|
||||
|
||||
| Env | Default | Purpose |
|
||||
| ----------------------- | ------------------ | ------------------------------------------------------------------- |
|
||||
| `DIFYCTL_R2_BASE` | — (required) | R2 public base, e.g. `https://pub-….r2.dev`. |
|
||||
| `DIFYCTL_CHANNEL` | `edge` | Channel to install. |
|
||||
| `DIFYCTL_INSTALL_DIR` | `$HOME/.local/bin` | Directory the binary is written to (`<dir>/difyctl`). |
|
||||
| `DIFYCTL_VERSION` | latest | Pin an exact published version. |
|
||||
| `DIFYCTL_COMMIT` | latest | Pin by git commit (short or full sha). |
|
||||
| `DIFYCTL_R2_PREFIX` | `difyctl` | R2 key root for the pointer JSONs (`manifest.json` / `index.json`). |
|
||||
| `DIFYCTL_R2_BIN_PREFIX` | `difyctl/bin` | R2 key root for binaries (the lifecycle/TTL target). |
|
||||
| Env | Default | Purpose |
|
||||
| ----------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------- |
|
||||
| `DIFYCTL_R2_BASE` | — (required) | R2 public base, e.g. `https://pub-….r2.dev`. |
|
||||
| `DIFYCTL_CHANNEL` | `edge` | Channel to install. |
|
||||
| `DIFYCTL_INSTALL_DIR` | `$HOME/.local/bin` | Directory the binary is written to (`<dir>/difyctl`). On Windows the default is `%LOCALAPPDATA%\difyctl\bin`. |
|
||||
| `DIFYCTL_PREFIX` | `$HOME/.local` | Used as `<prefix>/bin` when `DIFYCTL_INSTALL_DIR` is unset. On Windows the default is `%LOCALAPPDATA%\difyctl`. |
|
||||
| `DIFYCTL_VERSION` | latest | Pin an exact published version. |
|
||||
| `DIFYCTL_COMMIT` | latest | Pin by git commit (short or full sha). |
|
||||
| `DIFYCTL_R2_PREFIX` | `difyctl` | R2 key root for the pointer JSONs (`manifest.json` / `index.json`). |
|
||||
| `DIFYCTL_R2_BIN_PREFIX` | `difyctl/bin` | R2 key root for binaries (the lifecycle/TTL target). |
|
||||
|
||||
By default the channel pointer (latest build) is installed. Set `DIFYCTL_COMMIT` (e.g. `ce4af86`) or `DIFYCTL_VERSION` to install a specific past build — both resolve through the channel's `index.json`:
|
||||
|
||||
@@ -85,7 +98,7 @@ The same files install through the Vercel skills installer: `npx skills add lang
|
||||
|
||||
`get config [key]` prints the whole local config or one key; `set config <key> <value>` and `unset config <key>` change it. The only config key today is `http.timeout` (request timeout in milliseconds).
|
||||
|
||||
Tokens use the OS keychain by default, falling back to `tokens.yml` on hosts without one. On Linux without a DBus session (`DBUS_SESSION_BUS_ADDRESS` unset), the keychain would only hold the token until the session ends, so difyctl uses `tokens.yml` there too; `login --no-keyring` chooses the file outright. Config and cache files are written `0600`, their directory `0700`.
|
||||
Tokens use the OS keychain by default, falling back to `tokens.yml` in the config folder on hosts without one. On Linux without a DBus session (`DBUS_SESSION_BUS_ADDRESS` unset), the keychain would only hold the token until the session ends, so difyctl uses `tokens.yml` there too; `login --no-keyring` chooses the file outright. The catalog cache is kept in the config folder under `catalog/`; `DIFY_CACHE_DIR` is no longer used. Config and cache files are written `0600`, their directory `0700`.
|
||||
|
||||
| Env var | Effect |
|
||||
| ------------------- | ----------------------------------------------------------- |
|
||||
@@ -94,7 +107,6 @@ Tokens use the OS keychain by default, falling back to `tokens.yml` on hosts wit
|
||||
| `DIFY_WORKSPACE_ID` | Overrides the locally pinned workspace |
|
||||
| `DIFY_OUTPUT` | `json` or `text`; overrides the terminal/pipe detection |
|
||||
| `DIFY_CONFIG_DIR` | Overrides the config directory |
|
||||
| `DIFY_CACHE_DIR` | Overrides the catalog cache directory |
|
||||
|
||||
Resource access tokens can also be passed through `DIFY_TOKEN`. They can list
|
||||
their own workspace and discover only apps bound to that token; workspace
|
||||
@@ -108,7 +120,7 @@ Pass `--stream` on a streaming operation to print every event as one JSON line,
|
||||
difyctl run console_app chat --app-id … --query hello --inputs '{}' --stream
|
||||
```
|
||||
|
||||
`--only <event>` filters the streamed events to the named event types; repeat it to keep more than one. Without `--stream`, a streaming operation's events fold into `{status, text, outputs?, message_id?, conversation_id?, error?, hints}`.
|
||||
`--only <event>` filters the streamed events to the named event types; repeat it to keep more than one. Without `--stream`, a streaming operation's events fold into `{status, text, outputs?, message_id?, conversation_id?, run_id?, error?, hints}`.
|
||||
|
||||
## Exit codes
|
||||
|
||||
|
||||
@@ -12,8 +12,14 @@ Run an app with the op for its mode: `run console_app workflow`, `run console_ap
|
||||
|
||||
## Reading results
|
||||
|
||||
Streaming ops fold to `{status, text, outputs?, total_tokens?, message_id?, conversation_id?, error?, hints}`. `text.answer` is the reply; `text.by_source` appears only while `status` is `incomplete`. `status` is `ended`, `failed` (exit 1), `suspended` (a form is waiting; follow `hints`) or `incomplete` (the stream broke early). Any response may carry `hints: [{summary, op, input, form?}]`, the server's next steps: next page, confirm step, reply op, form submit. Fill any `null` in `input` and pass it back with `difyctl <op, dots as spaces> --input '<input>'`.
|
||||
Streaming ops fold to `{status, text, outputs?, total_tokens?, message_id?, conversation_id?, run_id?, error?, hints}`. `text.answer` is the reply; `text.by_source` appears only while `status` is `incomplete`. `status` is `ended`, `failed` (exit 1), `suspended` (a form is waiting; follow `hints`) or `incomplete` (stream broke early; exit 0, so check `status`). Any response may carry `hints: [{summary, op, input, form?}]`, the server's next steps: next page, confirm step, reply op, form submit. Fill any `null` in `input` and pass it back with `difyctl <op, dots as spaces> --input '<input>'`.
|
||||
|
||||
After `submit.run.form`, run its `get.run.event` hint to follow the run; repeat if it suspends again.
|
||||
|
||||
## Errors and exit codes
|
||||
|
||||
Errors are one envelope on stderr: `{"error":{"code","message","hint"?,"details"?,"schema"?}}`. Exit 2 is bad input (schema included), 4 not logged in or forbidden, 6 catalog unavailable or unknown op (run `difyctl refresh cache` or upgrade difyctl), 7 rate limited.
|
||||
Stderr envelope: `{"error":{"code","message","hint"?,"details"?,"schema"?,"http_status"?,"server"?}}`. `code` is difyctl's (`server_error` for server rejections); the server's code is `error.server.code` (e.g. `dsl_invalid`). `details`: `[{loc,msg}]`.
|
||||
|
||||
Exit: 2 bad input caught locally (incl. near-miss command); 1 server rejection or other failure; 4 not logged in (incl. unknown word while logged out), 401, 403; 6 catalog unavailable or `unknown_op`; 7 rate limited.
|
||||
|
||||
PowerShell: use `--input @file.json`, and `$env:VAR='v'; difyctl ...`.
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
1. `difyctl describe model_provider --provider <id>` (or `describe tool_provider`) shows `credential_form` and the saved `credentials` (names only).
|
||||
2. Ask the human for each form value. Never invent one, never print it, never write it into the working folder.
|
||||
3. Pass the values on stdin: `difyctl create model_provider credential --provider <id> --credentials @-` (for tools, `difyctl create tool_provider credential --provider <id> --credentials @-`), then write the JSON object to stdin.
|
||||
4. A 422 means the provider rejected the values; nothing was saved. Show the human the message and ask again.
|
||||
5. If another credential is already active, the hint offers to replace its values with `set`.
|
||||
4. Rejected (model 422, tool 400): nothing saved; show the message, ask again.
|
||||
5. Model providers only: if a credential is already active, the hint offers `set` to replace it.
|
||||
6. A tool provider whose `credential_types` lacks `api-key` uses OAuth. Ask the human to authorize it in the console.
|
||||
|
||||
Self-hosted or OpenAI-compatible models: `create model credential` with `--model`, `--model-type` and `--credentials @-`.
|
||||
|
||||
@@ -17,7 +17,7 @@ Log in only this way:
|
||||
|
||||
Never run `login` without `--no-wait`. It blocks until the human approves.
|
||||
|
||||
A script that already has a token skips login: set `DIFY_SERVER` and `DIFY_TOKEN`.
|
||||
A script that already has a token skips login: set `DIFY_SERVER` and `DIFY_TOKEN`. (v1's `DIFY_HOST` is not read.)
|
||||
|
||||
`--no-browser` prints the URL instead of opening one; always pass it as an agent. `--insecure` skips TLS verification and allows `http://` (local dev only).
|
||||
|
||||
@@ -26,7 +26,7 @@ A script that already has a token skips login: set `DIFY_SERVER` and `DIFY_TOKEN
|
||||
The token goes to the OS keyring by default. On Linux without a DBus session, difyctl uses a file instead, because the keyring there is lost when the session ends. In a sandbox, a container or a headless VM, the keyring can still be lost between sessions. There:
|
||||
|
||||
- Add `--no-keyring` to `login`, so the token goes to a file. Pass it on the `--no-wait` call; `--resume` remembers it.
|
||||
- Leave `DIFY_CONFIG_DIR` unset unless the default folder (`~/.config/difyctl`) is lost between sessions. If you set it, put it on every command (`DIFY_CONFIG_DIR=<dir> difyctl ...`): an `export` does not carry over when each command runs in a new shell. The pending login from `--no-wait` lives there too, so `--resume` needs the same value. A `not_logged_in` error names the folder it checked.
|
||||
- Leave `DIFY_CONFIG_DIR` unset unless the default folder is lost between sessions (macOS `~/.config/difyctl`, Linux `${XDG_CONFIG_HOME:-~/.config}/difyctl`, Windows `%APPDATA%\difyctl`). If you set it, put it on every command (`DIFY_CONFIG_DIR=<dir> difyctl ...`): an `export` does not carry over when each command runs in a new shell. The pending login from `--no-wait` lives there too, so `--resume` needs the same value. A `not_logged_in` error names the folder it checked.
|
||||
|
||||
## Workspace
|
||||
|
||||
@@ -34,4 +34,4 @@ The token goes to the OS keyring by default. On Linux without a DBus session, di
|
||||
|
||||
## Files
|
||||
|
||||
`DIFY_CONFIG_DIR` moves the login and token files; `DIFY_CACHE_DIR` moves the catalog cache.
|
||||
`DIFY_CONFIG_DIR` holds login, tokens and catalog. `DIFY_CACHE_DIR` is unused.
|
||||
|
||||
Reference in New Issue
Block a user