# How Dify Offline Plugin Packages Work with `--no-index` and `--find-links`

> Learn how dify offline plugin packages install in air-gapped environments using pip install --no-index --find-links for seamless local dependency resolution.

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

---

**The `dify-plugin-repackaging` utility creates self-contained wheel files that install in air-gapped environments using `pip install --no-index --find-links` to bypass PyPI and resolve dependencies exclusively from a local directory.**

The `junjiem/dify-plugin-repackaging` repository provides a specialized build utility for creating **self-contained, offline-installable plugin packages** for the Dify platform. By wrapping compiled Go binaries in Python wheel metadata, the tool generates platform-specific `.whl` files that distribute without internet connectivity. This workflow leverages specific pip flags to guarantee reproducible installations in secure or isolated environments.

## The Three-Stage Offline Packaging Workflow

### Stage 1: Building the Plugin Wheels

The **[`plugin_repackaging.sh`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin_repackaging.sh)** script serves as the primary build orchestrator. Located in the repository root, it compiles the plugin binary for each target platform using `go build`, then packages the result into a Python wheel with the required metadata. All generated wheels are placed into a local **package store directory** (`./packages` by default), creating a complete offline repository.

### Stage 2: Publishing the Store

Once built, the `./packages` directory functions as a standalone distribution unit. You can transfer this folder to target machines via USB drive, internal HTTP server, or CI artifact storage. Because the directory contains all necessary wheel files, no external PyPI repository connection is required for distribution to air-gapped environments.

### Stage 3: Installing with `--no-index` and `--find-links`

On the target host, pip installs the plugin using two specific flags that work in tandem. The **`--no-index`** flag prevents pip from querying the public PyPI index entirely, while **`--find-links`** points pip to the local `./packages` directory containing the wheel files. This combination forces pip to resolve the plugin and its dependencies exclusively from the filesystem, eliminating all network calls.

## Why `--no-index` and `--find-links` Matter for Air-Gapped Environments

**`--no-index`** guarantees that pip never attempts to reach out to the public PyPI index or any external package repository. This behavior is essential for environments with strict security controls or no internet access, ensuring that the installation process fails safely rather than hanging attempting external connections.

**`--find-links`** supplies pip with a custom "index" in the form of a simple directory or HTML file containing wheel files. Pip treats each `.whl` file in the specified directory as a package candidate and resolves the requested version directly from the filesystem without requiring a full PyPI-compatible server infrastructure.

The [`plugin_repackaging.sh`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin_repackaging.sh) script also generates a **[`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt)** file that pins the exact plugin version. This allows the installation command to reference specific builds while maintaining the offline constraint.

## Practical Implementation Steps

Build wheels for multiple target platforms on your build machine:

```bash
./plugin_repackaging.sh build \
    --output-dir ./packages \
    --targets linux/amd64 darwin/arm64

```

Transfer the generated package store to the offline target host:

```bash
scp -r ./packages user@offline-host:/opt/dify-plugin

```

Install the plugin offline using the generated requirements file:

```bash
pip install --no-index --find-links ./packages -r requirements.txt

```

For single-wheel installations without a requirements file, reference the wheel directly:

```bash
pip install --no-index --find-links ./packages dify_plugin-1.2.3-py3-none-any.whl

```

## Key Files and Their Roles

- **[`plugin_repackaging.sh`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin_repackaging.sh)**: The main build script that compiles Go assets, creates platform-specific wheels, and writes the [`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt) file.
- **`./packages/`**: The default local package store directory containing the generated `.whl` files (e.g., `dify-plugin-linux-amd64.whl`).
- **[`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt)**: Auto-generated file containing exact version pins to ensure reproducible installations across environments.
- **`Dockerfile`**: Provides a containerized build environment for running the packaging script reproducibly.
- **`images/install_plugin_via_local.png`**: Visual diagram illustrating the offline installation workflow.

## Summary

- The `dify-plugin-repackaging` tool generates platform-specific wheels containing pre-compiled binaries for the Dify platform.
- The `./packages` directory acts as a self-contained package store that requires no external PyPI access for distribution.
- **`--no-index`** prevents pip from accessing external package indexes, ensuring compatibility with air-gapped networks.
- **`--find-links`** directs pip to resolve and install packages exclusively from the local wheel directory.
- This workflow guarantees that the exact binary version built on the build machine installs on the target host without requiring compilation tools or internet access.

## Frequently Asked Questions

### What is the purpose of the `--no-index` flag in pip?

The `--no-index` flag tells pip to ignore the default PyPI package index and any other configured indexes. This prevents pip from attempting to download packages from the internet, making it essential for installing packages in offline or air-gapped environments where external network access is restricted or unavailable.

### How does `--find-links` differ from `--index-url`?

While `--index-url` points pip to an alternative PyPI-compatible repository server (such as a private Nexus or Artifactory instance), `--find-links` points to a simple directory path or HTML file containing wheel files. In the context of `dify-plugin-repackaging`, `--find-links` treats the local `./packages` folder as a flat repository, allowing pip to discover and install wheels without hosting a full package index server.

### Can I install a single wheel file without using requirements.txt?

Yes. If you only need to install a specific plugin version, you can reference the wheel file directly in the pip command: `pip install --no-index --find-links ./packages dify_plugin-1.2.3-py3-none-any.whl`. This approach bypasses the need for a [`requirements.txt`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/requirements.txt) file while still utilizing the offline package store and preventing PyPI access.

### Why does the build process create Python wheels instead of distributing raw binaries?

Wheels are the standard Python packaging format that pip understands natively. By wrapping the compiled Go binary in a wheel structure according to Python packaging standards, the [`plugin_repackaging.sh`](https://github.com/junjiem/dify-plugin-repackaging/blob/main/plugin_repackaging.sh) script allows pip to handle installation, dependency resolution, and uninstallation consistently across different platforms. This approach ensures the compiled binary installs to the correct location within the Python environment while maintaining compatibility with standard Python tooling.