Dify DSL Visualizer

Preview and edit Dify app DSL (workflow / advanced-chat) YAML files as an interactive graph, directly inside VS Code — before importing them into Dify.
Source code, issues and releases: https://github.com/real-akimoto-akira/dify-dsl-visualizer
Built for the AI-generated-DSL workflow: have an agent write the YAML, eyeball the graph, fix the wiring and prompts, then import a file you already trust.
Features
- Graph preview of
workflow.graph with Dify-style node cards, branch handles (IF/ELSE, classifier classes, human-input actions), mini-map, search and auto layout.
- Two-way editing — everything you change on the canvas is written back into the YAML:
- drag nodes to reposition them
- drag between handles to create connections
- Delete to remove nodes (attached edges are cleaned up) or connections
- add new nodes from a typed palette with valid default payloads
- edit node settings in the inspector (title, model, prompts, code, template, URL, …) or the full
data block as raw YAML
- Surgical YAML writes. Only the region you actually edited is rewritten. Comments, quoting style, block scalars and key order elsewhere in the file are preserved byte-for-byte.
- Native undo/redo — every change is a normal VS Code text edit, so Cmd+Z works and the file stays dirty until you save.
- Live sync — editing the YAML by hand (or by an agent) updates the graph immediately.
- Publish straight to Dify — push the DSL into a Dify Enterprise workspace with one click, then jump to the app in the Console.
Install
Either of these works:
Usage
1. Open the graph
Open any Dify DSL .yml / .yaml file, then start the graph editor in whichever way suits you:
- Command palette — Cmd/Ctrl+Shift+P → Dify DSL: Open Graph Preview
- Explorer — right-click the file → Dify DSL: Open Graph Preview
- Open With… — right-click the file → Open With… → Dify DSL Graph
- Editor title bar — the graph icon, shown only for files that look like a Dify DSL
The preview opens beside the source so you can watch both at once. The custom editor is registered with
priority: "option", so it never hijacks ordinary YAML files — plain YAML keeps opening in the text editor.

2. Read the graph
Each node is drawn as a card whose colour and icon come from its Dify node type:
- Title —
data.title, falling back to the node id
- Type badge — the humanized
data.type (LLM, Code, IF / ELSE, Human Input, …)
- Summary — the one detail that matters most for that type: model name for
llm, METHOD url for
http-request, language for code, case count for if-else, output count for end, …
- Description —
data.desc, clamped to three lines
Branching nodes render one labelled output port per branch — IF / ELSE for if-else, one per class for
question-classifier, one per action for human-input — and the edges carry the same labels, so you can see at a
glance which path a connection belongs to. Iteration and loop containers are drawn as dashed boxes around their
children.
Use the search box to filter: matching nodes stay bright, everything else dims to 25%. The mini map and the
zoom controls sit in the bottom corners; scroll to zoom, drag the empty canvas to pan.

3. Inspect and edit a node
Click a node to open it in the inspector on the right.
- Settings tab — typed fields tailored to the node type: model provider/name/temperature and a full prompt
editor for
llm, language + code for code, Jinja2 template for template-transform, method/URL/headers/body
for http-request, form content and user actions for human-input, and so on.
- Raw YAML tab — the node's entire
data block as editable YAML, for anything the typed fields don't cover.
Press Apply to commit, Reset to discard.
Every committed change is written straight into the YAML file as a normal VS Code edit, so the file goes dirty,
Cmd/Ctrl+Z undoes it, and only the bytes you actually changed are rewritten —
comments, quoting style and key order everywhere else stay untouched.
Selecting nothing shows the app panel instead: name, description, mode, DSL version and node/edge counts.
4. Rewire the graph
| Action |
How |
| Move a node |
Drag it — the new position is saved to the YAML |
| Connect two nodes |
Drag from a node's right-hand port onto another node's left-hand port |
| Inspect a connection |
Click the edge — the inspector shows source/target and both handles |
| Delete |
Select a node or edge and press Delete / Backspace, or use the button in the inspector |
| Add a node |
+ Node in the toolbar, then pick a type from the grouped palette |
Deleting a node also removes every edge attached to it. New nodes are created with a valid default data payload
for their type, so the result still imports into Dify. Duplicate connections are rejected with a notice.
5. Jump between the graph and the source
- Double-click a node (or the ⤢ button in the inspector) to open the YAML beside the graph with the cursor on
that node's definition.
- YAML in the toolbar opens the whole source file.
- Editing the YAML by hand — or having an agent rewrite it — updates the graph immediately, and vice versa.
| Button |
Effect |
Touches the file? |
| Fit view |
Zooms/pans the camera so the whole graph is visible |
no |
| Re-layout |
Recomputes every node position into a left-to-right layered layout and writes them into the YAML |
yes |
| Map |
Toggles the mini map |
no |
| Wrap |
Soft-wraps long lines in the code / YAML editors instead of scrolling horizontally |
no |
| ☀ / ☾ / ◐ |
Theme: follow VS Code (auto) → light → dark |
no |
| YAML |
Opens the underlying source |
no |
| Publish → |
Uploads the DSL to Dify |
no (writes to Dify) |
| ⚙ |
Opens the Dify environment panel; shows the active environment name |
no |
Drag the divider between the canvas and the inspector to resize it, or double-click the divider to reset it.
Toolbar toggles, the theme and the inspector width are remembered per editor.
If Re-layout appears to do nothing, your DSL is already laid out on the same grid it computes
(x steps of node-width + 64, columns vertically centred) — it reports how many nodes it moved.
Files that cannot be drawn
If the YAML is not a Dify DSL, fails to parse, or is an app mode without a workflow graph (agent-chat, chat,
completion), the editor explains why and offers a button to open the source instead.
Publishing to Dify
Uses the Dify Enterprise Admin API.
Click the ⚙ gear in the graph toolbar (it shows the active environment name), or run
Dify DSL: Configure Dify Environment. The panel edits these values:
| Key |
Required |
What it is |
NAME |
yes |
Local label for the environment, e.g. dify-dev. |
ADMIN_API_ENDPOINT |
yes |
Enterprise Admin API base URL including /admin-api/v1, e.g. https://enterprise-platform.dify.dev/admin-api/v1. This is the enterprise host, not the Console host. Used for workspace resolution and DSL import/export. |
SECRET_KEY |
yes |
Admin API Secret Key (Bearer token) issued in the Dify Enterprise admin panel. |
WORKSPACE_NAME |
yes |
Exact workspace name, e.g. MyDepartment. Resolved to a UUID via GET /workspaces?name=… on every publish. |
CONSOLE_URL |
no |
Console base URL, e.g. https://console-platform.dify.dev. Only used to build the Open in Console link <CONSOLE_URL>/app/<APP_ID>/workflow; a trailing /apps is stripped automatically. |
CREATOR_EMAIL |
no |
Workspace member the app is created as. Empty falls back to the workspace owner returned by the API. |
All six values live in the difyDsl.environments setting. The panel header tells you which scope it writes to
(user vs. workspace settings.json), and Open in Settings jumps straight there.
Security note. SECRET_KEY is stored in plain text in settings.json, the same as every other field.
That keeps setup simple and portable, but it also means the key can leak through version control, Settings Sync,
backups or a screen share. Prefer User settings over workspace settings, add .vscode/settings.json to
.gitignore when you keep environments per repo, and rotate the key if it is ever exposed.
Publish
Test connection in the panel to confirm the endpoint, key and workspace resolve.

Hit Publish → in the toolbar (or Dify DSL: Publish to Dify). The extension resolves the workspace,
uploads the DSL, re-exports the created app to verify name/node count, and offers a link to the Console.

Notes:
- The Admin API always creates a new app; it cannot overwrite an existing one. Publishing twice gives you two apps.
The confirmation dialog says so — disable it with
difyDsl.confirmBeforePublish once you are used to it.
completed-with-warnings usually means your DSL version is older than the server's current_dsl_version, or the
app references a plugin/model that is not installed in the target environment.
- Multiple environments are supported; switch in the panel or with Dify DSL: Select Active Dify Environment.
Settings
| Setting |
Default |
Description |
difyDsl.environments |
[] |
Dify environments (name, Admin API endpoint, workspace, console URL, creator email). Contains no secrets. |
difyDsl.activeEnvironment |
"" |
Environment used by Publish. Defaults to the first one. |
difyDsl.confirmBeforePublish |
true |
Confirm before publishing, since each publish creates a new app. |
difyDsl.persistNodePosition |
true |
Write node positions back to the YAML when a node is dragged. |
difyDsl.persistViewport |
false |
Write the canvas pan/zoom back to workflow.graph.viewport, and restore it when opening the graph. |
Supported node types
start, end, answer, llm, agent, knowledge-retrieval, knowledge-index, datasource, if-else,
question-classifier, code, template-transform, http-request, tool, variable-aggregator,
assigner / variable-assigner, parameter-extractor, iteration, loop, document-extractor,
list-operator, human-input, note and any trigger-* node. Unknown node types still render and can be
edited through the raw YAML tab.
Development
npm install
npm run watch # esbuild watch for extension + webview
Press F5 (Run Extension) to launch an Extension Development Host with dify-dsl-samples/ opened.
npm run typecheck # tsc --noEmit for both projects
npm run build # production bundles
npm run package # produces a .vsix (requires @vscode/vsce)
Project layout
| Path |
Purpose |
src/extension.ts |
Activation, commands, context keys |
src/difyEditorProvider.ts |
CustomTextEditorProvider, webview host, document sync |
src/dsl/model.ts |
YAML → graph model, Dify DSL detection |
src/dsl/patch.ts |
Range-based YAML patcher (minimal text edits) |
src/dsl/edit.ts |
Graph edit operations → YAML patches |
src/dify/api.ts |
Enterprise Admin API client (workspaces, DSL import/export) |
src/dify/environment.ts |
Environment settings + SecretStorage |
src/dify/commands.ts |
Publish / test-connection / configuration commands |
shared/protocol.ts |
Types shared by host and webview |
webview/ |
React + React Flow canvas, inspector, palette |
Installing elsewhere
Download the .vsix from the latest release, then:
code --install-extension dify-dsl-visualizer-<version>.vsix
Or in VS Code: Extensions → ... → Install from VSIX...
To build one yourself:
npm ci
npm run package
Releasing
.github/workflows/release.yml builds and publishes on every v* tag:
npm version 0.3.1 --no-git-tag-version # keep package.json in sync
git commit -am "chore: release v0.3.1"
git tag v0.3.1
git push origin main --tags
The workflow fails fast if the tag does not match package.json's version, then attaches the .vsix to a
GitHub Release and uploads it as a build
artifact. It can also be run manually via workflow_dispatch to produce an artifact without releasing.
License
MIT