nextflow-io/agent-skills/migrate-nextflow-code
- community
Checking that the SKILL.md file is still in the repository.
Migrate a Nextflow pipeline to new language patterns.
Install
npx vskill@latest install nextflow-io/agent-skills/migrate-nextflow-codeSKILL.md
Migrate Nextflow Code
Migrate a Nextflow pipeline to new language patterns. Follow best practices from the Nextflow docs. Use nextflow lint to validate code as you go. Verify that the pipeline produces the same results before/after migration.
Requirements
Requires Nextflow 26.10 or later for the nextflow lint command with type checking.
Requires nf-core template 3.0.0 or later, if applicable. If the pipeline has a .nf-core.yml, check which version of nf-core/tools last generated its template. If nf_core_version is unspecified or less than 3.0.0, stop and tell the user to upgrade their template first. This will resolve syntax errors in the template code and provide a cleaner baseline.
Migrations
Apply each migration requested by the user, one at a time, in the following order. Each migration requires the ones before it.
Each migration links the relevant docs. Consult these docs when you aren't sure how to do something. For example, which type to use, which method to use for a given type, or how to use a specific channel operator. Don't just guess or try to work from past knowledge. The linter can guide you, but the docs provide examples and best practices.
Strict syntax
Update a pipeline to comply with nextflow lint. Pipelines written before the introduction of the strict syntax parser may contain patterns that are no longer valid.
- Run the linter over the entire project:
nextflow lint -o concise . - Fix each issue without changing behavior. Keep changes minimal.
- Re-run the linter as needed and iterate until there are no errors.
Reference:
Topic channels
Replace the ch_versions plumbing in a pipeline with a versions topic channel.
- Send process version outputs to the
versionstopic. Replaceemit: versionswithtopic: versions. Replace the YAML versions file with a tuple of process name, tool name, and eval command. - Consume the
versionstopic withchannel.topic('versions')when writing the versions file. Group elements by process. - Delete the
ch_versionsplumbing.
Any process downstream of the topic channel must not emit to that topic, or else the pipeline deadlocks.
Reference:
Static typing
Migrate a pipeline to use typed processes, typed workflows, typed parameters, and records. Migrate components from the bottom up. Use nextflow lint to type-check as you go.
- Migrate processes to typed processes
- Migrate workflows to typed workflows
- Migrate the pipeline parameters to typed parameters
- Re-run the linter as needed until there are no errors.
Rules:
- Use destructured record inputs/outputs in processes.
- Check carefully whether a process
pathinput/output should be a single file (Path) or a file collection (List<Path>,Set<Path>, etc). - Every process should output a single wide record. Every workflow should join related outputs into a wide record channel. This makes it easier to migrate to workflow outputs.
- Use record types to describe channel inputs/outputs for workflows. Define record types with their workflow, not a shared types module.
- If the pipeline uses the
nf-schemaplugin, update it to version 2.7.2 or later to avoid runtime issues with static typing. - Params used by the script must be declared in the script. Params that only affect config settings should be declared in the config file. Config can override script param defaults, but ideally in a profile (e.g.
test). - The global
paramsrecord should only be used in the entry workflow. Pass params to processes and workflows as explicit inputs. Bundle related params into a single workflow input with a record type (e.g.workflow ALIGNER->record AlignerParams) so that you can passparamsdirectly from the entry workflow. - Use type coercion (
x as Type) only when the type is genuinely unknown, such aschannel.topic().
Reference:
Workflow outputs
Migrate a pipeline to use workflow outputs. Replace all publishDir directives with a top-level output block that produces the same output directory tree.
If the pipeline hasn't been migrated to static typing and records, stop and warn the user about this. The output block requires process outputs to be propagated to the entry workflow, which leads to an excessive number of workflow emits if the pipeline still uses narrow tuples (e.g. (meta, file)). Combining narrow tuple channels into wide record channels makes it feasible to publish channels through the output block.
- Identify all
publishDirdirectives in processes and config files. - For each publisher, determine: which process(es) are targeted, which files are published, and where they are published.
- For each published output, propagate the corresponding process outputs to the entry workflow (via
emit:) and publish them (viapublish:). - Add a top-level
outputblock with a declaration andpathdirective for each published channel. - Define global publishing behavior in config (
outputDir,workflow.output.mode, etc). Override publish settings in theoutputblock as needed. - Delete the
publishDirdirectives.
Rules:
- Consult the docs to learn the
publishDiroptions, outputpathdirective, andworkflow.outputoptions. Figure out how to map the former to the latter. - Prefer one combined per-sample output over many per-tool outputs. Create an index file only if the pipeline already does it (see
collectFilebelow). - You don't need to manually extract or flatten files when publishing a channel. Nextflow automatically extracts files from published values (lists, maps, records, tuples).
- The
collectFileoperator withstoreDir:is another way to publish a file. RemovestoreDir:and publish it to theoutputblock instead. You might even be able to replace it with an outputindexdirective, e.g. if it is a samplesheet of the per-sample outputs. - Some pipelines have a catch-all
publishDirin the main config. This can likely be deleted.
Reference:
Pipeline composition
Make a pipeline composable, so that it can be executed directly or included by another pipeline.
If the pipeline hasn't been migrated to static typing, or doesn't have the params and output blocks, stop and warn the user about this. Pipeline composition depends heavily on these language features.
- Review the
paramsblock. Determine which params can be refactored as dataflow types. A samplesheet input can be refactored as a channel of records (Channel<Sample>). An index file input can be wrapped as a dataflow value (Value<Path>). Unless the user says otherwise, refactor samplesheet inputs and leave the rest.
- Check for global params usage. The pipeline should not use global params outside the entry workflow and
outputblock. It should already be publishing all outputs through theoutputblock instead ofpublishDirdirectives.
- Check for project-level assets (
projectDir,bin,lib). The pipeline should avoid these in favor of composable alternatives (params, moduleresources/andmoduleDir, helper functions).
- Check for process configuration (
conf/modules,ext.args,withName). Refactor it by moving it into pipeline code (see below).
The biggest issue you will likely encounter is ext config. nf-core modules use ext for certain inputs such as tool args and filename prefix/suffix. Users can then override these settings easily from config. A pipeline may specify its own defaults in config with process selectors. This makes the pipeline harder to compose.
The solution is to refactor the pipeline's ext config as pipeline code:
- Modules take
args/prefix/suffixas explicit inputs and resolve them astask.ext.<name> ?: <input> ?: <default>. Users can still override any tool at runtime with config. - Each
extsetting moves into pipeline code. Add the setting to each sample record withmaporcombinedepending on whether it varies per-sample. - Use helper functions to separate complex
extsettings from workflow logic. Build an options map first, then render it to a CLI string with a separatecli()helper.
Reference:
Validation
After each migration, verify behavior against baseline using the project's test suite. For example:
- Run before/after with test profile:
nextflow run . -profile test,docker - nf-test:
nf-test test - Stub run:
nextflow run . -stub
Critical Rules
- One migration at a time. Finish one migration before starting another one.
- Read the docs. Consult the linked docs when you aren't sure how to do something.
- Preserve behavior. The pipeline should produce the same outputs before/after the migration.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/migrate-nextflow-code/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/nextflow-io/agent-skills/migrate-nextflow-code)