# What Is the .difypkg Format? Internal Structure and Repackaging Guide

> Discover the .difypkg format, a ZIP archive for Dify plugins. Learn its internal structure, including manifest, source code, and Python wheels for offline installation.

- Repository: [Junjie.M/dify-plugin-repackaging](https://github.com/junjiem/dify-plugin-repackaging)
- Tags: internals
- Published: 2026-03-05

---

**The `.difypkg` format is a standard ZIP archive that bundles a Dify plugin's manifest, source code, and Python wheel dependencies into a single offline-installable package.**

The Dify platform distributes plugins as self-contained `.difypkg` files. According to the [junjiem/dify-plugin-repackaging](https://github.com/junjiem/dify-plugin-repackaging) source code, this format enables portable distribution by embedding all third-party dependencies directly within the archive, eliminating the need for external network access during installation.

## What Is a .difypkg File?

A `.difypkg` file is **nothing more than a renamed ZIP archive** that follows a specific internal layout expected by the Dify plugin runtime. When you upload a `.difypkg` to Dify, the platform extracts this archive, reads the plugin metadata, and installs the bundled Python packages from the embedded `wheels/` directory rather than downloading them from PyPI.

This design guarantees **offline installation capability**. By pre-downloading all required binary wheels and patching [`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt) to use local paths, the repackaging script ensures the plugin installs reliably in air-gapped environments or networks with restricted egress.

## Internal Structure of a .difypkg Archive

When you inspect a `.difypkg` using standard ZIP tools, you will find the following predictable layout:

```text
your-plugin-1.2.3.difypkg   (ZIP archive)
│
├─ plugin.yaml              ← Plugin manifest (name, version, author)
├─ requirements.txt         ← Python dependencies (patched for offline use)
├─ wheels/                  ← Pre-downloaded wheel files (*.whl)
│   ├─ requests-2.31.0-py3-none-any.whl
│   └─ numpy-1.24.0-cp39-cp39-manylinux2014_x86_64.whl
├─ src/                     ← Plugin source code (Python package)
│   ├─ __init__.py
│   └─ … (module files)
├─ .difyignore              ← Files to exclude during upload (optional)
└─ README, LICENSE, etc.

```

### The Plugin Manifest (plugin.yaml)

The file [`plugin.yaml`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin.yaml) (or occasionally [`plugin.json`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin.json)) serves as the entry point Dify reads to discover the plugin's metadata. It declares the plugin's unique identifier, version, author information, and runtime configuration. Without this file at the archive root, Dify cannot recognize or load the package.

### Offline Dependencies (requirements.txt and wheels/)

The [`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt) file located at the archive root controls dependency resolution. After repackaging, this file always begins with the directive:

```text
--no-index --find-links=./wheels/

```

This line instructs `pip` to install packages exclusively from the local `wheels/` directory, bypassing PyPI entirely. The `wheels/` folder contains all binary wheel files (`.whl`) required by the plugin, including platform-specific compiled extensions for Linux, macOS, or Windows.

### Source Code and Assets (src/ and .difyignore)

The `src/` directory contains the actual Python implementation of the plugin. Any importable package layout works here as long as the entry points declared in [`plugin.yaml`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin.yaml) resolve correctly. The optional `.difyignore` file functions like `.gitignore`, specifying patterns for files and directories that Dify should exclude when processing the plugin upload.

## How the Repackaging Script Modifies .difypkg

The [`plugin_repackaging.sh`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin_repackaging.sh) script in the junjiem/dify-plugin-repackaging repository automates the process of converting a standard Dify plugin into an offline-capable package. The workflow performs five distinct operations on the original `.difypkg`:

1. **Extract the original archive** using `unzip -o ${PACKAGE_PATH} -d ${CURR_DIR}/${PACKAGE_NAME}` to create a working directory with the standard layout.

2. **Download dependencies** by executing `pip download … -d ./wheels` to fetch every wheel specified in the original [`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt) into a new `wheels/` subdirectory.

3. **Patch requirements.txt** using `sed -i '1i\--no-index --find-links=./wheels/' requirements.txt` (on Linux) to insert the offline-install directive at the top of the file, ensuring the plugin uses bundled wheels exclusively.

4. **Make the binary executable** with `chmod 755 ${CURR_DIR}/${CMD_NAME}` on the `dify-plugin-<os>-<arch>` binary, which is required for the final packaging step.

5. **Re-package the directory** by calling `${CMD_NAME} plugin package ${CURR_DIR}/${PACKAGE_NAME} -o ${CURR_DIR}/${PACKAGE_NAME}-${PACKAGE_SUFFIX}.difypkg --max-size 5120`. This invokes the Dify-plugin CLI to rebuild the ZIP archive with the embedded wheels and modified requirements, producing the final offline-ready `.difypkg`.

## Why Dify Uses the ZIP Format

The choice of ZIP as the container format provides three critical advantages for the Dify ecosystem:

- **Portability**: A single file can be uploaded via Dify's web UI, REST API, or command-line interface without complex streaming or multi-part uploads.
- **Offline installation**: By bundling wheels inside the archive, plugins install successfully in environments without internet access or behind strict corporate firewalls.
- **Integrity verification**: Dify can compute cryptographic hashes of the entire archive before extraction, enabling signature verification and tamper detection prior to installation.

## Inspecting and Creating .difypkg Files Manually

Because `.difypkg` files are standard ZIP archives, you can manipulate them using common command-line tools without specialized software.

To inspect the contents of any `.difypkg`:

```bash
unzip -l my-plugin-0.1.0.difypkg

```

To manually create a `.difypkg` from scratch:

```bash
mkdir myplugin && cd myplugin

# Create plugin.yaml, src/, requirements.txt, etc.

zip -r ../my-plugin-0.1.0.difypkg .

```

Note that for production use, you should use the official `dify-plugin` binary with the `plugin package` command (as shown in the repackaging script) to ensure the archive meets Dify's size limits and validation requirements.

## Summary

- **`.difypkg` is a ZIP archive** containing a Dify plugin's manifest, source code, and dependencies.
- **The `wheels/` directory** contains pre-downloaded Python packages, making the plugin offline-installable.
- **[`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt) must start** with `--no-index --find-links=./wheels/` to force local wheel installation.
- **The repackaging script** extracts the original package, downloads wheels, patches the requirements file, and re-zips the contents using the `dify-plugin` CLI.
- **Manual inspection** is possible using standard `unzip` commands since the format follows standard ZIP specifications.

## Frequently Asked Questions

### How do I open or inspect a .difypkg file?

Use any standard ZIP utility. Run `unzip -l filename.difypkg` to list contents without extracting, or `unzip filename.difypkg -d ./output` to extract the archive to a specific directory. The format contains no encryption or compression beyond standard DEFLATE.

### What happens if the wheels/ directory is missing from a .difypkg?

Without the `wheels/` directory and the corresponding `--no-index --find-links=./wheels/` line in [`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt), Dify will attempt to download dependencies from PyPI during installation. This fails in offline environments and may introduce version conflicts if PyPI packages differ from those tested during development.

### Can I manually edit files inside a .difypkg without the repackaging script?

Yes. Extract the archive with `unzip`, modify the files (such as updating [`plugin.yaml`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin.yaml) or adding assets), then repackage with `zip -r`. However, if you need to add offline wheel support, you must manually run `pip download` to populate `wheels/` and edit [`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt) to include the local find-links directive before rezipping.

### What is the maximum size for a .difypkg file?

According to the junjiem/dify-plugin-repackaging implementation, the `dify-plugin` CLI enforces a maximum package size of 5120 MB (5 GB) when using the `--max-size 5120` flag during the `plugin package` command. Exceeding this limit requires removing unnecessary assets or splitting functionality into multiple plugins.