Skip to main content

Developing modules

Learn how to create modules and share them through the Nextflow module registry.

Creating a module

Use the module create command to scaffold a new module with the required files:

$ nextflow module create myorg/my-module

If you omit the name, the command prompts you for details:

$ nextflow module create

The command creates a module directory with the following files:

  • main.nf: The module script containing your process definition.
  • meta.yml: The module spec describing metadata, inputs, and outputs.
  • README.md: Documentation for the module.

See module create for the full command reference.

Module structure

Registry modules follow a standard directory structure:

modules/
└── myorg/
└── my-module/
├── .module-info # Integrity checksum
├── README.md # Documentation
├── main.nf # Module script
├── meta.yml # Module spec
├── resources/ # Optional: Module resources
└── templates/ # Optional: Process script templates

Local modules that are not intended for publishing do not need to follow this structure, although it is recommended as a best practice.

main.nf

The main.nf file contains the process definition. For example, a simple module wrapping FastQC:

process FASTQC {
tag "$meta.id"
label 'process_medium'

conda 'bioconda::fastqc=0.12.1'
container 'biocontainers/fastqc:0.12.1--hdfd78af_0'

input:
tuple val(meta), path(reads)

output:
tuple val(meta), path("*.html"), emit: html
tuple val(meta), path("*.zip") , emit: zip

script:
"""
fastqc $reads --threads $task.cpus
"""
}

Registry modules are subject to the following constraints:

  • The module must contain a single script called main.nf
  • The module must define a single process
  • The module must not define any named workflows
  • The module may define an entry workflow to override the default behavior of module run.
  • The module may define any number of functions

Local modules can define any number of processes, workflows, and functions. As a best practice, each process and named workflow should be defined in its own script.

meta.yml

The meta.yml file contains the module's metadata, including its name, version, description, authors, and input/output specifications. The registry uses this file to display module information and generate usage templates.

README.md

The README.md file provides documentation for the module. It should describe what the module does, the tools it wraps, and any configuration requirements.

resources

Modules can include resource files in the resources/ directory.

When running the module with Wave, the contents of resources/ are mounted into the root directory of the task container.

For example, given a module with the following structure:

my-module/
├── main.nf
└── resources/
├── data/
| └── file.txt
└── usr/
└── bin/
└── hello.sh

The process script can use these files as follows:

process hello {
container 'quay.io/nextflow/bash'

script:
"""
cat /data/file.txt
hello.sh
"""
}

Module resources can be used without Wave or containerization, with the following limitations:

  • The nextflow.enable.moduleBinaries feature flag must be enabled in the pipeline script.

  • The pipeline work directory must be in a local or shared file system. Remote object storage is not supported without Wave.

  • Only executable scripts in resources/usr/bin/ are made accessible to the process script.

templates

Modules can include process script templates in the templates/ directory.

For example, given a module with the following structure:

my-module/
|── main.nf
└── templates/
└── hello.sh

The module's process can use the script template as follows:

process hello {
input:
val STR

script:
template 'hello.sh'
}

Generating a module spec

Use the module spec command to generate or update the meta.yml file from the module's main.nf:

$ nextflow module spec myorg/my-module

Use -dry-run to preview the generated spec without writing to disk:

$ nextflow module spec -dry-run myorg/my-module

When generating the module spec for the first time, provide required fields directly to avoid TODO placeholders in the generated file:

$ nextflow module spec \
-namespace myorg \
-version 1.0.0 \
-description "Quality control of raw sequencing reads" \
-license MIT \
-author "@myname" \
./modules/myorg/my-module

When updating an existing module spec, it is incorporated into the new file.

See module spec for the full command reference.

Validating a module

Use the module validate command to check that a module is ready for publishing:

$ nextflow module validate myorg/my-module

The command verifies that:

  • All required files are present (main.nf, meta.yml, README.md).
  • The module spec contains all required fields (name, version, description, and license).

See module validate for the full command reference.

Testing a module

Before publishing, test your module by running it directly:

$ nextflow module run myorg/my-module --input 'test-data/*.fastq.gz'

The command executes the module as a standalone run, allowing you to verify that inputs are correctly declared, the process runs successfully, and the correct outputs are produced.

For more thorough testing, create a small wrapper workflow that exercises the module:

include { MY_MODULE } from './modules/myorg/my-module'

workflow {
input_ch = channel.fromPath('test-data/*.fastq.gz')
results_ch = MY_MODULE(input_ch)
results_ch.view()
}