# How to Use CWL for Bioinformatics: Step-by-Step Guide

By the end of this guide you will be able to install the Common Workflow Language (CWL) reference runner, write a CWL tool wrapper around a real command-line bioinformatics tool, chain several tools into a workflow, run everything inside containers, scatter one step over many input files, and validate your documents before a long compute run. You will also know the mistakes that trip up most first-time CWL authors and how CWL compares with Nextflow and Snakemake when you are choosing a bioinformatics workflow manager.

Before you start, have the following on hand:

- A Linux or macOS machine (or a Windows machine with WSL2) with Python 3.8 or newer
- Permission to run `pip install cwltool`
- Docker installed and running, or Singularity/Apptainer if you are on an HPC system without root access
- A small test FASTQ file and, for the workflow example, a reference FASTA with its BWA index files
- Basic comfort with the command line and YAML indentation

CWL is a written specification, not a single program. You describe each tool and each workflow in YAML, and a separate engine (an executor) reads those documents and runs the steps. The most widely used executor is `cwltool`, the reference implementation maintained by the Common Workflow Language project. This guide uses `cwltool` throughout.

## Why CWL for Bioinformatics

A pipeline that runs on your laptop but breaks on your cluster is a liability. CWL was created specifically to solve that problem. It is a platform-independent specification for describing workflows, so the same document can run on a standalone server, a cluster, or a cloud platform, which is exactly the portability gap that motivated tools like CWL-Airflow, a lightweight manager that adds CWL support to Apache Airflow [1].

This portability has practical consequences for research quality. A study of RNA-Seq, ChIP-Seq, and germline [variant calling pipelines](/knowledge/bioinformatics/variant-calling-pipelines-gatk-deepvariant) implemented in CWL reproduced the results of two previously published Chronic Lymphocytic Leukemia studies and achieved high accuracy detecting germline SNPs and small indels against Genome in a Bottle truth sets, with the authors crediting CWL's reproducibility and reusability, especially when combined with containerization [2].

CWL also matters where heterogeneous computing environments are the norm. H3ABioNet, the Pan-African bioinformatics network spanning 27 research institutions in 17 African countries, built CWL workflows for variant calling, 16S rDNA analysis, genotyping and GWAS, and SNP imputation precisely because implementing scalable, portable, reproducible workflows across such varied infrastructure is hard [3].

Finally, CWL is a common exchange format in collaborative science. The ICGC-TCGA DREAM SMC-RNA challenge required every benchmark entry to be a containerized workflow, which made 77 fusion detection entries and 65 isoform quantification entries reusable through CWL and Docker containers [4].

## CWL Concepts You Need First

Four ideas cover most of the language.

**CommandLineTool** describes a single program invocation: the base command, its inputs, where inputs go on the command line, what files it produces, and how to find those outputs. This is the unit of reuse.

**Workflow** describes a directed graph of steps. Each step points to a CommandLineTool (or another workflow, called a subworkflow) and wires inputs to outputs of earlier steps.

**Inputs and outputs** are typed. A parameter can be a `string`, `int`, `boolean`, `File`, `Directory`, or arrays of these. File inputs can declare `secondaryFiles`, extra files such as a BWA index that must sit next to the main file.

**Requirements and hints** declare what an executor must provide. `requirements` are mandatory. `hints` are optional suggestions, and the most important hint is `DockerRequirement`, which names a container image. If the executor cannot honor a hint, it may still run the tool locally. This separation of tool description from execution is what lets one document run under Docker on a laptop and under Singularity on a shared cluster.

Two conventions you will see constantly:

- `$(inputs.x)` refers to an input parameter inside a tool's arguments. `$(steps.align.outputs.sam)` refers to an output of a named workflow step.
- `$(runtime.cores)` and `$(runtime.ram)` refer to resources the executor assigns, which keeps your tool wrappers hardware-agnostic.

## Step-by-Step: Build and Run a CWL Bioinformatics Workflow

### Step 1: Install and Verify cwltool

```bash
python3 -m pip install --upgrade pip
python3 -m pip install cwltool
cwltool --version
```

Expected output (your version number will differ):

```
cwltool 3.1.20240112164112
```

If `cwltool, version` prints a version, you have a working executor. Keep it current. Older runners cannot read newer CWL features such as the conditional `when` clause introduced in CWL 1.2.

### Step 2: Write a Minimal CommandLineTool

Create a directory for the tutorial and a file named `hello.cwl`:

```bash
mkdir cwl-tutorial && cd cwl-tutorial
cat > hello.cwl << 'EOF'
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: CommandLineTool
baseCommand: echo
inputs:
  message:
    type: string
    inputBinding:
      position: 1
outputs: []
EOF
```

Line by line:

- `cwlVersion: v1.0` pins the spec version. CWL 1.0 is the oldest widely supported version and a safe default for shared pipelines.
- `class: CommandLineTool` tells the executor this document wraps a program, not a graph.
- `baseCommand: echo` is the fixed part of the command line.
- `message` is an input of type `string` with `position: 1`, meaning it is appended as the first free argument.
- `outputs: []` means the tool writes nothing you need to keep.

### Step 3: Run It with a Job File

Create a job file, which supplies values for the inputs:

```bash
cat > hello-job.yml << 'EOF'
message: hello world
EOF
cwltool hello.cwl hello-job.yml
```

Expected output:

```
INFO [workflow ] start
INFO [workflow ] final process status is success
{}
```

For a tool with no outputs, the result object is empty. Add `-outdir results` to any run to control where output files land.

A useful shortcut when you do not want to hand-write a job file:

```bash
cwltool --make-template hello.cwl
```

This prints a YAML skeleton listing every input, which you then fill in.

### Step 4: Wrap a Real Tool with a Container Hint

Real bioinformatics tools need specific versions and dependencies. The standard practice is to pair a CWL wrapper with a container from BioContainers, a registry of bioinformatics software images. Here is a wrapper for FastQC, the read quality checker, with a container hint:

```bash
cat > fastqc.cwl << 'EOF'
cwlVersion: v1.0
class: CommandLineTool
label: FastQC read quality report
hints:
  DockerRequirement:
    dockerPull: quay.io/biocontainers/fastqc:v0.11.9--0
baseCommand: fastqc
arguments:
  - prefix: "--outdir"
    value: "."
inputs:
  reads:
    type: File
    inputBinding:
      position: 1
outputs:
  html_report:
    type: File
    outputBinding:
      glob: "*.html"
  zip_archive:
    type: File
    outputBinding:
      glob: "*.zip"
EOF
```

Notes on the parameters that matter:

- `hints: DockerRequirement` with `dockerPull` names the image. Pull tags from the BioContainers registry rather than guessing them.
- The output `glob` patterns must match files the tool actually creates in its working directory. FastQC writes one `.html` report and one `.zip` archive per input file.
- If your tool has version-dependent flags, add a `SoftwareRequirement` under `requirements` listing the package and version so other people know what you tested.

Run it against a local FASTQ:

```bash
cat > fastqc-job.yml << 'EOF'
reads:
  class: File
  path: sample_R1.fastq.gz
EOF
cwltool --outdir qc fastqc.cwl fastqc-job.yml
```

Expected output:

```
INFO [workflow ] start
INFO [step fastqc] start
INFO [job fastqc] running in container ...
INFO [step fastqc] completed
INFO [workflow ] completed
{
    "html_report": {
        "location": "file:///home/you/cwl-tutorial/qc/sample_R1_fastqc.html",
        "basename": "sample_R1_fastqc.html",
        "class": "File",
        "size": 312454
    },
    "zip_archive": {
        "location": "file:///home/you/cwl-tutorial/qc/sample_R1_fastqc.zip",
        "basename": "sample_R1_fastqc.zip",
        "class": "File",
        "size": 289102
    }
}
Final process status is success
```

Check that the two files exist and open the HTML report. If the glob had failed to match anything, the run would end with a `permanentFailure` and a message about collecting outputs.

### Step 5: Build a Two-Step Workflow

Now wrap BWA-MEM for alignment and samtools sort, then wire them into a workflow. First the alignment tool, `bwa-mem-tool.cwl`:

```bash
cat > bwa-mem-tool.cwl << 'EOF'
cwlVersion: v1.0
class: CommandLineTool
label: Align reads with bwa mem
hints:
  DockerRequirement:
    dockerPull: quay.io/biocontainers/bwa:0.7.17--h516909a_7
baseCommand: bwa
arguments:
  - value: ["mem", "-t", "$(runtime.cores)"]
    position: -1
inputs:
  reference:
    type: File
    secondaryFiles: [.amb, .ann, .bwt, .pac, .sa]
    inputBinding:
      position: 1
  reads:
    type: File
    inputBinding:
      position: 2
outputs:
  sam:
    type: File
    outputBinding:
      glob: "aligned.sam"
stdout: aligned.sam
EOF
```

Key points:

- `secondaryFiles` is what makes CWL carry the BWA index automatically. When the executor stages `genome.fa`, it also stages `genome.fa.amb` through `genome.fa.sa` from the same directory.
- The `arguments` list prepends `mem -t N` after `bwa`, using `$(runtime.cores)` so the wrapper works on any machine regardless of core count.
- `stdout: aligned.sam` redirects the tool's standard output into a named file that the output `glob` then picks up.

Next the sort tool, `samtools-sort-tool.cwl`:

```bash
cat > samtools-sort-tool.cwl << 'EOF'
cwlVersion: v1.0
class: CommandLineTool
label: Sort aligned reads into BAM
hints:
  DockerRequirement:
    dockerPull: quay.io/biocontainers/samtools:1.9--h8571acd_11
baseCommand: samtools
arguments:
  - value: ["sort"]
    position: -1
  - prefix: "-@"
    value: "$(runtime.cores)"
    position: -1
  - prefix: "-o"
    value: "sorted.bam"
    position: -1
inputs:
  sam:
    type: File
    inputBinding:
      position: -1
outputs:
  bam:
    type: File
    outputBinding:
      glob: "sorted.bam"
EOF
```

Now the workflow itself, `align-sort.cwl`:

```bash
cat > align-sort.cwl << 'EOF'
cwlVersion: v1.0
class: Workflow
inputs:
  reference: File
  reads: File
outputs:
  sorted_bam:
    type: File
    outputSource: sort/bam
steps:
  align:
    run: bwa-mem-tool.cwl
    in:
      reference: reference
      reads: reads
    out: [sam]
  sort:
    run: samtools-sort-tool.cwl
    in:
      sam: align/sam
    out: [bam]
EOF
```

The wiring reads top to bottom. The workflow takes `reference` and `reads`, feeds both into the `align` step, takes `align/sam` and feeds it into `sort`, and publishes `sort/bam` as the workflow output `sorted_bam`. The `outputSource` path uses the step name, a slash, and the output name. A typo there is one of the most common CWL errors, so double-check step names.

Prepare a reference and run:

```bash
bwa index genome.fa
cat > align-sort-job.yml << 'EOF'
reference:
  class: File
  path: genome.fa
reads:
  class: File
  path: sample_R1.fastq.gz
EOF
cwltool --outdir out align-sort.cwl align-sort-job.yml
```

Expected output:

```
INFO [workflow ] start
INFO [step align] start
INFO [step align] completed
INFO [step sort] start
INFO [step sort] completed
INFO [workflow ] completed
{
    "sorted_bam": {
        "location": "file:///home/you/cwl-tutorial/out/sorted.bam",
        "basename": "sorted.bam",
        "class": "File"
    }
}
Final process status is success
```

Verify the result with samtools directly:

```bash
samtools flagstat out/sorted.bam
```

You should see a summary table of mapped and paired read counts. Compare the total read count against your input FASTQ to confirm nothing was dropped.

### Step 6: Scatter One Step Across Many Samples

Batch processing is where declarative workflows pay off. Change the workflow to accept an array of FASTQs and scatter the alignment step:

```bash
cat > align-sort-scatter.cwl << 'EOF'
cwlVersion: v1.0
class: Workflow
requirements:
  ScatterFeatureRequirement:
    scatterMethod: dotproduct
inputs:
  reference: File
  reads: File[]
outputs:
  sorted_bams:
    type: File[]
    outputSource: sort/bam
steps:
  align:
    scatter: reads
    run: bwa-mem-tool.cwl
    in:
      reference: reference
      reads: reads
    out: [sam]
  sort:
    run: samtools-sort-tool.cwl
    in:
      sam: align/sam
    out: [bam]
EOF
```

Three additions drive the behavior:

- `ScatterFeatureRequirement` declares the workflow uses scatter, so the executor must support it. All mainstream executors do.
- `scatter: reads` on the `align` step tells the engine to run that step once per element of the `reads` array, in parallel if resources allow.
- `align/sam` becomes an array after scattering, and the downstream `sort` step receives the whole array element by element automatically, preserving order.

The matching job file lists several FASTQs:

```bash
cat > scatter-job.yml << 'EOF'
reference:
  class: File
  path: genome.fa
reads:
  - class: File
    path: sample_R1.fastq.gz
  - class: File
    path: sample_R2.fastq.gz
  - class: File
    path: sample_R3.fastq.gz
EOF
cwltool --outdir out align-sort-scatter.cwl scatter-job.yml
```

The final result object now contains `sorted_bams` as an array of three file locations. Scatter plus `secondaryFiles` plus containers is the core pattern behind production CWL pipelines, including the published RNA-Seq, ChIP-Seq, and germline variant calling pipelines evaluated against GIAB samples [2].

### Step 7: Validate, Cache, and Run Anywhere

Before submitting a long run, validate every document. Validation checks structure, types, and wiring without executing anything:

```bash
cwltool --validate align-sort-scatter.cwl
```

Expected output:

```
Workflow check complete
align-sort-scatter.cwl is valid CWL.
```

On clusters without Docker, execute the same documents with Singularity or Apptainer:

```bash
cwltool --singularity --outdir out align-sort-scatter.cwl scatter-job.yml
```

The `-singularity` flag swaps the container runtime while leaving your CWL untouched. For incremental reruns during development, add a cache directory so completed steps are skipped:

```bash
cwltool --cachedir /tmp/cwl-cache --outdir out align-sort-scatter.cwl scatter-job.yml
```

If a step fails halfway, fix the tool wrapper and rerun the same command. Steps whose inputs and outputs are unchanged are reused from the cache instead of recomputed.

## cwltool Options That Matter

| Option | What it does | When to use it |
|--|--|--|
| `-validate` | Checks the CWL document and exits without running | Before every submission to a cluster or queue |
| `-outdir DIR` | Writes all declared outputs into one directory | Every run, so results are never lost in temporary directories |
| `-cachedir DIR` | Caches intermediate outputs for incremental reruns | Iterating on a long workflow |
| `-singularity` | Executes container hints with Singularity or Apptainer | HPC systems where Docker is unavailable |
| `-make-template` | Prints a YAML input skeleton for a document | Starting a new job file without typos |
| `-strict` | Treats validation warnings as errors | Hardening a pipeline before sharing it |
| `-debug` | Prints full stack traces and command logs | Diagnosing a failed step |
| `-quiet` | Suppresses info logging | Long runs where log volume matters |

## Common Errors and How to Fix Them

**"Tool definition failed validation".** The document is structurally wrong. The detailed lines beneath the message name the offending field. Typical causes are a misspelled `cwlVersion` (for example `v1.o` instead of `v1.0`), a missing `class`, indentation errors in YAML, or an `outputSource` that does not match any step output. Fix the named field and rerun with `-validate` until the document passes.

**`[E::bwa_idx_load_from_disk] fail to locate the index files`.** BWA cannot find its index. Your job file points at a bare FASTA with no `.amb`, `.ann`, `.bwt`, `.pac`, `.sa` files beside it, or your tool wrapper forgot the `secondaryFiles` declaration. Run `bwa index genome.fa`, keep the six files in one directory, and make sure the wrapper declares them. If the files genuinely cannot travel with the reference, some executors support `secondaryFiles` entries with a `listing` or URL pattern, but the simplest fix is staging the index files with the FASTA.

**Docker errors such as `docker: Error response from daemon: manifest unknown`.** The image tag in `dockerPull` does not exist or was removed. Copy the exact tag from the BioContainers registry page for your tool and version, then test the pull in isolation with `docker pull <image>` before rerunning the workflow.

**A message about a missing required input parameter, naming a field such as `reference`.** The job YAML key does not match the workflow input name, or you forgot the key entirely. Compare the job file against `cwltool, make-template align-sort.cwl`, which lists every expected key with its type.

**Type errors where a value "expects a File".** You passed a plain string path where the input type is `File`. In the job YAML, wrap the path:

```yaml
reads:
  class: File
  path: sample_R1.fastq.gz
```

Strings without `class: File` are the single most common job-file mistake for newcomers.

**"Cannot collect workflow output" ending in `permanentFailure`.** The step ran but no file matched the output `glob`. Open the step's working directory (the path cwltool prints in its logs) and see what the tool actually produced, then adjust the glob. Tools that write files into subdirectories need globs like `results/*.html`, and tools that need an explicit output path flag may need an `arguments` entry forcing the filename you glob for.

**An executor refusing a feature, for example conditional steps, with an old runner.** Upgrade with `python3 -m pip install, upgrade cwltool`. Pin the version in a requirements file if a shared cluster enforces a specific runner.

## CWL Bioinformatics Tips

**Separate tool wrappers from workflows from the start.** Keep every CommandLineTool in its own file and import them from workflows with `run:`. Published, reusable CWL pipelines such as the RNA-Seq, ChIP-Seq, and variant calling pipelines that reproduced published CLL results follow this layout, and it is what makes individual tools testable in isolation [2].

**Pin software versions in the container tag, not just the tool name.** `quay.io/biocontainers/fastqc:v0.11.9-0` names an exact build. A bare `dockerPull: fastqc` resolves to whatever the registry serves that day, which silently breaks reproducibility.

**Use `runtime.cores`, `runtime.ram`, and `ResourceRequirement` instead of hard-coded thread counts.** The same wrapper then runs with 2 cores on a laptop and 32 on a cluster node without edits, which is precisely the portability CWL was designed for [1].

**Run `cwltool, validate` as a preflight check in your submission script.** A two-second validation that catches a typo beats a three-hour queue wait that dies at step one.

**Build on existing CWL rather than starting from a blank file.** The Rcwl project provides an R interface to CWL along with more than 100 pre-built tools and pipelines in RcwlPipelines, queryable and reusable from within R [5]. The Playbook Workflow Builder takes this further with a card-based web interface, optionally assisted by a large language model, and completed workflows are compatible with CWL [6]. Challenge repositories are another source of battle-tested wrappers, as the SMC-RNA benchmark left behind CWL and Docker versions of every contributing method [4].

**Keep your job YAML files under version control next to the CWL.** A pipeline is only reproducible if the exact inputs, paths, and parameter values that produced a result are recorded alongside the code.

## Common Mistakes and Limitations

**Treating CWL as a scripting language.** CWL documents are declarative data. You cannot embed procedural logic, and attempts to force loops and conditionals into tool wrappers produce fragile documents. Move logic into the tools themselves or into `ScatterFeatureRequirement`, `SubworkflowFeatureRequirement`, and the CWL 1.2 conditional `when` clause.

**Confusing requirements and hints.** Putting a container in `hints` and assuming it always runs is a mistake on executors that ignore hints. If correct execution depends on a specific container or feature, declare it under `requirements`.

**Forgetting `secondaryFiles`.** Aligners, variant callers, and index-based tools fail at runtime with cryptic tool-level errors when companion files are missing. Declare every companion file in the wrapper, because the executor will not guess that `genome.fa` needs `genome.fa.bwt`.

**Writing output globs that are too loose.** A glob of `*` will happily match temporary files, logs, and half-written outputs. Globs should name exactly the files you intend to publish downstream.

**Assuming CWL alone gives reproducibility.** CWL provides portability and declarative wiring. Reproducibility requires the container tag, the CWL document, the job file, and the reference data versions to all be pinned together. The published evaluations of CWL pipelines pair CWL with containerization and explicit version information for all software precisely for this reason [2].

**Expecting a single best workflow manager.** A systematic evaluation of [workflow management](/knowledge/bioinformatics/snakemake-vs-nextflow-workflow-architectures) systems, including CWL, Nextflow, and WDL across local, HPC, and cloud settings, concluded that the right choice is a function of both the language and engine features and of adoption and collaboration patterns within your community [7]. CWL's formal specification and portability focus is a strength for shared, multi-institution pipelines, but a lab standardized on another system may be better served by staying there.

**Overwrapping one-off analyses.** For a single exploratory run of three commands, a shell script is honest and fast. CWL earns its overhead when a pipeline will be rerun, shared, scaled across samples, or executed on infrastructure you do not control, which is the situation H3ABioNet optimized for across dozens of heterogeneous sites [3].

## CWL Compared with Nextflow and Snakemake

![Comparison table of CWL, Nextflow and Snakemake across language, portability, best fit and main trade-off.](/article-images/illustrations/cwl-bioinformatics-manager-choice.webp)

All three are mainstream choices for a bioinformatics workflow manager, and honest guidance starts with what they optimize for.

CWL is a formal, executor-agnostic specification. Your documents do not belong to one engine, and the reference runner is complemented by executors that add scheduling, cloud, and service capabilities on top of the same documents. This makes CWL the natural interchange format for consortia, benchmarks, and platforms that must run other people's pipelines. The Playbook Workflow Builder exports CWL rather than a proprietary format for exactly this reason [6].

Nextflow uses a Groovy-based domain-specific language with a mature engine, strong cloud and cluster support, and a large user community. Snakemake adapts the Make model to Python, which makes it approachable if your team already writes Python. Both are excellent tools with active ecosystems.

The comparative evidence in the literature is broad rather than decisive. The systematic evaluation in Scientific Reports assessed CWL, Nextflow, and WDL, along with Swift/T, on language expressiveness, modularity, scalability, robustness, reproducibility, interoperability, and ease of development across local, HPC, and cloud executions of a variant-calling pipeline, and its conclusion is that the choice depends on intrinsic language and engine features together with adoption and collaboration patterns in your field [7]. Practically, that means three questions decide it:

1. Who else must run your pipeline? If external groups, platforms, or benchmark systems need to execute it as-is, the portability of a formal spec is the deciding factor, and CWL or WDL are built for that.
2. What does your team already know? A Python-heavy lab ramping up on Snakemake will be productive faster than on any declarative spec.
3. What infrastructure do you target? Verify that your chosen engine supports your scheduler (SLURM, SGE), cloud, or Kubernetes before committing.

Choosing one does not exile you from the others. Tool wrappers are the reusable asset, and community efforts such as the workflows in RcwlPipelines and the challenge repositories lower the cost of maintaining CWL versions alongside other formats [5].

## Frequently Asked Questions

### What is CWL and why should I use it for bioinformatics?

CWL, the Common Workflow Language, is a YAML-based specification for describing bioinformatics tools and workflows independently of the engine that runs them. You use it because the same documents run on a laptop, an HPC cluster, or the cloud, and because published CWL pipelines have demonstrated reproducible results in RNA-Seq, ChIP-Seq, and variant calling analyses [2].

### Do I have to write CWL by hand?

No. You can generate workflows interactively with the Playbook Workflow Builder, which lets users click cards representing analysis steps or use an LLM-assisted chat, and the completed workflows are compatible with CWL [6]. From R, the Rcwl package lets you build and run CWL pipelines programmatically [5].

### Can I run CWL workflows on an HPC cluster without Docker?

Yes. Use an executor or mode that supports Singularity or Apptainer, for example `cwltool, singularity`, and the same CWL documents run unchanged on shared systems where users cannot install Docker.

### Nextflow vs Snakemake versus CWL, which should I pick?

Choose based on who must run your pipeline, what your team already knows, and your target infrastructure. A systematic evaluation of workflow management systems found the choice depends on language and engine features plus adoption and collaboration patterns in your community, rather than a universal winner [7].

### How do I find existing CWL workflows instead of writing my own?

Look at repositories of published pipelines, such as the CWL implementations of RNA-Seq, ChIP-Seq, and germline variant calling workflows [2], the Bioconductor RcwlPipelines collection of more than 100 pre-built tools and pipelines [5], and benchmark repositories like the SMC-RNA challenge archive of containerized fusion and isoform methods [4].

### How do I validate a CWL workflow before a big run?

Run `cwltool, validate yourworkflow.cwl`, which checks structure, types, and step wiring without executing anything. Add `-strict` to promote warnings to errors before sharing the pipeline.

### Does CWL support parallel processing over many samples?

Yes. Declare `ScatterFeatureRequirement`, add `scatter` to a step, and provide an array input. The executor runs one instance per array element, in parallel when resources allow, and downstream steps receive the arrayed results automatically.

### Which CWL version should I write against?

CWL 1.0 is the most widely supported baseline and a safe choice for shared pipelines. CWL 1.2 adds conveniences such as conditional steps with the `when` clause. Pin the version in every document and use a current executor, since older runners cannot read newer features.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What is CWL and why should I use it for bioinformatics?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "CWL, the Common Workflow Language, is a YAML-based specification for describing bioinformatics tools and workflows independently of the engine that runs them. You use it because the same documents run on a laptop, an HPC cluster, or the cloud, and because published CWL pipelines have demonstrated reproducible results in RNA-Seq, ChIP-Seq, and variant calling analyses."
      }
    },
    {
      "@type": "Question",
      "name": "Do I have to write CWL by hand?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No. You can generate workflows interactively with the Playbook Workflow Builder, which lets users click cards representing analysis steps or use an LLM-assisted chat, and the completed workflows are compatible with CWL. From R, the Rcwl package lets you build and run CWL pipelines programmatically."
      }
    },
    {
      "@type": "Question",
      "name": "Can I run CWL workflows on an HPC cluster without Docker?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. Use an executor or mode that supports Singularity or Apptainer, for example cwltool with the singularity flag, and the same CWL documents run unchanged on shared systems where users cannot install Docker."
      }
    },
    {
      "@type": "Question",
      "name": "Nextflow vs Snakemake versus CWL, which should I pick?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Choose based on who must run your pipeline, what your team already knows, and your target infrastructure. A systematic evaluation of workflow management systems found the choice depends on language and engine features plus adoption and collaboration patterns in your community, rather than a universal winner."
      }
    },
    {
      "@type": "Question",
      "name": "How do I find existing CWL workflows instead of writing my own?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Look at repositories of published pipelines, such as CWL implementations of RNA-Seq, ChIP-Seq, and germline variant calling workflows, the Bioconductor RcwlPipelines collection of more than 100 pre-built tools and pipelines, and benchmark repositories like the SMC-RNA challenge archive of containerized fusion and isoform methods."
      }
    },
    {
      "@type": "Question",
      "name": "How do I validate a CWL workflow before a big run?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Run cwltool with the validate flag on your workflow file, which checks structure, types, and step wiring without executing anything. Add the strict flag to promote warnings to errors before sharing the pipeline."
      }
    },
    {
      "@type": "Question",
      "name": "Does CWL support parallel processing over many samples?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. Declare ScatterFeatureRequirement, add scatter to a step, and provide an array input. The executor runs one instance per array element, in parallel when resources allow, and downstream steps receive the arrayed results automatically."
      }
    },
    {
      "@type": "Question",
      "name": "Which CWL version should I write against?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "CWL 1.0 is the most widely supported baseline and a safe choice for shared pipelines. CWL 1.2 adds conveniences such as conditional steps with the when clause. Pin the version in every document and use a current executor, since older runners cannot read newer features."
      }
    }
  ]
}
</script>

## Sources

1. [CWL-Airflow: a lightweight pipeline manager supporting Common Workflow Language.](https://pubmed.ncbi.nlm.nih.gov/31321430/)
2. [Software pipelines for RNA-Seq, ChIP-Seq and germline variant calling analyses in common workflow language (CWL).](https://pubmed.ncbi.nlm.nih.gov/38025398/)
3. [Developing reproducible bioinformatics analysis workflows for heterogeneous computing environments to support African genomics.](https://pubmed.ncbi.nlm.nih.gov/30486782/)
4. [A community challenge to evaluate RNA-seq, fusion detection, and isoform quantification methods for cancer discovery.](https://pubmed.ncbi.nlm.nih.gov/34146471/)
5. [Bioconductor toolchain for reproducible bioinformatics pipelines using Rcwl and RcwlPipelines.](https://pubmed.ncbi.nlm.nih.gov/33772584/)
6. [Playbook workflow builder: Interactive construction of bioinformatics workflows.](https://pubmed.ncbi.nlm.nih.gov/40179105/)
7. [Design considerations for workflow management systems use in production genomics research and the clinic.](https://pubmed.ncbi.nlm.nih.gov/34737383/)