Dify plugin builder
Skill xxzxzmai-droid/dify-builder-skills/dify-plugin-builder
Codex/Claude skills for generating Dify agents and plugins
npx -y skills add xxzxzmai-droid/dify-builder-skills --skill dify-plugin-builderAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Build and package a Dify plugin (a .difypkg file) from a description of what the tool should do. Use this whenever the user wants to create, build, or package a Dify plugin / tool plugin / 插件 / .difypkg — e.g. "做一个把文本转成可下载文件的Dify插件", "帮我做个Dify工具插件调用某个API", "build a Dify plugin that converts markdown to PDF", "package this as a .difypkg". Trigger even if they don't say ".difypkg". The skill scaffolds the plugin from a proven template, fills in the tool logic, and packages it correctly for air-gapped/内网 Dify with bundled offline wheels.
SKILL.md
5.1 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
Dify Plugin Builder
Scaffold, implement, and package a Dify tool plugin into an installable .difypkg for
air-gapped/内网 Dify. Assume the target Dify server cannot reach the internet. The template and
packaging scripts encode several non-obvious gotchas that otherwise cost hours.
Non-negotiable delivery rule
Every generated plugin must be fully offline installable: requirements.txt must use
--no-index + --find-links=./wheels/, and wheels/*.whl must be included in the .difypkg.
Do not deliver a plugin package that depends on the Dify server reaching PyPI.
Workflow
- Understand the tool. What does it take in, what does it produce (text / structured JSON / a downloadable file)? Does it need network or a credential/API key?
- Scaffold the plugin. Prefer the deterministic scaffold over manual copying:
python3 scripts/scaffold_plugin.py /tmp/<plugin_name> --name <plugin_name> --author <author_id> --label-zh "<中文名>" --label-en "<English name>" --description-zh "<中文描述>" --description-en "<English description>"Use--mode downloadable-file|text|json; the default is a downloadable-file tool that already usesmeta["filename"]. - Fill in or replace the tool logic (see
references/plugin-guide.mdfor the full SDK reference):manifest.yaml: setauthor,name, labels, description.authormust be lowercase[a-z0-9_]; it forms theprovider_idprefix.provider/<provider>.yaml+.py: rename, set identity. No credentials → leave_validate_credentialsreturning. Needs an API key → declare it and validate.tools/<tool>.yaml+.py: define parameters and the_invokelogic. The template's example tool returns a downloadable file — adapt or replace it.- Rename the referenced files and update the
source:/tools:paths to match.
- Prepare offline dependencies (required):
- If this machine can reach PyPI for the target platform:
bash scripts/fetch_offline_wheels.sh /tmp/<plugin_name> 3.12 manylinux2014_aarch64 - If not, copy wheels from a plugin already verified on the same Dify server:
python3 scripts/prepare_offline_plugin.py /tmp/<plugin_name> --wheels-from /path/to/verified/wheels - If neither is available, stop and ask for the target server platform or a verified wheels directory. Do not package an online-only plugin.
- If this machine can reach PyPI for the target platform:
- Package:
bash scripts/pack_plugin.sh /tmp/<plugin_name> <plugin_name>.difypkgThe script useszip -D(no directory entries) — required, or install fails withread tools: is a directory. It also refuses to package unless offline requirements andwheels/*.whlare present. - Deliver the
.difypkgand tell the user how to install (Dify → 插件 → 安装插件 → 本地文件), plus any post-install step (select a model, fill credentials).
Offline dependency source
The Dify plugin daemon installs Python deps during plugin install. In our scenario it has no
internet. Always bundle wheels. manylinux2014_aarch64 is common for ARM64 servers; use
manylinux2014_x86_64 for x86_64. If unsure, ask for the server architecture before packaging.
Output a downloadable file from a tool (common, and full of traps)
self.create_blob_message(blob=bytes, meta={...}) is the way. Two traps the template already handles:
- Filename: dify-api reads
meta["filename"](NOTfile_name). Wrong key → file is named with a random hash. - Extension / clickable download: the file's URL ends in an extension guessed from the mime type
(yaml/many types →
.bin). The downloaded name comes frommeta["filename"]only when the request URL has?as_attachment=true. So in the workflow that calls this tool, append&as_attachment=trueto the file'surlbefore presenting it (a small code node can do this).
Full SDK details (message types, session.file.upload, signing) are in
references/plugin-guide.md — read it before writing non-trivial tool logic.
Sanity-check before packaging
python3 -m py_compile /tmp/<plugin_name>/main.py /tmp/<plugin_name>/provider/*.py /tmp/<plugin_name>/tools/*.py
python3 -c "import yaml,glob; [yaml.safe_load(open(f)) for f in glob.glob('/tmp/<plugin_name>/**/*.yaml',recursive=True)]"
After packaging, confirm 目录条目=0 and manifest在根=1 (the script prints both).
When changing this skill, run:
python3 -m unittest tests.test_plugin_builder
What ships with it: 15 files
25.2 KB alongside SKILL.md, 7 of them executable
agents/
- openai.yaml249 B
assets/
- plugin-template/_assets/icon.svg268 B
- plugin-template/main.pyruns148 B
- plugin-template/manifest.yaml724 B
- plugin-template/PRIVACY.md165 B
- plugin-template/provider/my_provider.pyruns445 B
- plugin-template/provider/my_provider.yaml387 B
- plugin-template/requirements.txt207 B
- plugin-template/tools/my_tool.pyruns1.1 KB
- plugin-template/tools/my_tool.yaml1006 B
references/
- plugin-guide.md7.1 KB
scripts/
- fetch_offline_wheels.shruns1.0 KB
- pack_plugin.shruns1.8 KB
- prepare_offline_plugin.pyruns2.5 KB
- scaffold_plugin.pyruns8.2 KB