CLI tool
FelixKrueger/TrimGalore avatar
FelixKrueger/TrimGalore

Trim Galore v2: a Rust rewrite of the NGS trimming standard

Consistent adapter and quality trimming for NGS, with extra functionality for RRBS data

579 stars163 forksRustGPL-3.0

At a glance

What is it?
Trim Galore is the adapter and quality trimming tool for next-generation sequencing data, and version 2.0 replaced the Perl scripts with a single Rust binary that keeps the same CLI, output filenames and report format while adding poly-G and poly-A trimming, per-pair adapter detection, a bundled FastQC and optional clumpify compression. It is GPL-3.0 licensed and installable from crates.io, bioconda or Docker.
Who is it for?
Trim Galore v2 fits a sequencing pipeline that has to keep working with the same command lines and the same output files it had with the Perl version, and which now needs poly-G handling, a bundled FastQC or a Docker image that does not need Java. It does not fit a team that needs the very latest unreleased behaviour in production, since the dev branch build is explicitly a development install.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What changed when Trim Galore moved from Perl to Rust

Trim Galore v2.0 is a faithful Rust rewrite, described as a single binary with zero external dependencies, designed as a drop-in replacement for the v0.6.x scripts and pipelines. The promise is explicit: same CLI, same output filenames, same report format.

That framing is the important part of the project. Trim Galore is the kind of tool that ends up baked into hundreds of published pipelines and shell scripts, and a rewrite that changed the command line or the report layout would break all of them. The Rust version keeps the interface and changes the implementation, which is why the migration notes exist as a separate document with what changed, benchmarks, and migration notes.

On top of the rewrite, version 2.0 added poly-G auto-detection and trimming for 2-colour instruments, a generic poly-A trimmer, per-pair adapter auto-detection, and cleaner multi-adapter invocation, with a repeatable -a and -a2 replacing Perl's embedded-string syntax.

The tool's core job is unchanged. It performs consistent quality and adapter trimming for next-generation sequencing data, with special handling for RRBS libraries, and the description names NGS as the target. The users are people running sequencing pipelines, and the practical audience for this version is the same people who ran the Perl version and now have to decide whether to switch.

Adapter detection, poly-G and the RRBS special case

The feature list is where the sequencing knowledge shows.

Adapter auto-detection identifies Illumina, Nextera, Small RNA and BGI/DNBSEQ adapters from the first 1M reads. Stranded Illumina stays explicit through the --stranded_illumina flag, because its sequence is ambiguous with Nextera. That is the kind of detail that only matters to someone who has had a pipeline silently trim the wrong adapter, and it is a good example of the tool being explicit rather than clever.

Multi-adapter support lets you specify multiple adapters by repeating -a and -a2, or point at a file with -a "file:adapters.fa", with optional multi-round trimming through -n.

Poly-G trimming removes no-signal G-runs at the 3' end of Read 1 and Read 2 from 2-colour instruments, named as NovaSeq, NextSeq and NovaSeq X. The documentation explains the mechanism, which is the useful part: the artefact is sequencer-induced, an overrun calls no signal as G, so it shows up at the 3' end of every read regardless of strand. It is auto-detected from the data and you can opt out with --no_poly_g.

Poly-A trimming is built in without external tools and is recommended for mRNA-seq and poly-A-selected RNA-seq libraries.

RRBS handling is the feature the project description leads with. It removes MspI end-repair artefacts and supports both directional and non-directional libraries, which is the difference between a usable reduced representation bisulphite sequencing pipeline and one that needs a lot of manual work around the MspI overhang.

Quality trimming is Phred based from the 3' end using the BWA algorithm, and for NextSeq and 2-colour instruments the --nextseq N and --2colour N options apply 2-colour-aware quality trimming and replace -q.

Installing v2, and the four ways to get the binary

There are four documented installation routes, and the choice matters for how you pin a pipeline.

From crates.io, which requires the Rust toolchain at 1.88 or newer:

bash
cargo install trim-galore

From bioconda:

bash
conda install -c bioconda trim-galore

Building from source:

bash
git clone https://github.com/FelixKrueger/TrimGalore.git
cd TrimGalore
cargo build --release
# Binary is at target/release/trim_galore

And the latest unreleased changes straight from the development branch, which overwrites an existing install, for example a v2.0.0 install from crates.io:

bash
cargo install --git https://github.com/FelixKrueger/TrimGalore --branch dev trim-galore --force

The Docker route uses multi-arch images for amd64 and arm64 from GitHub Container Registry:

bash
docker run --rm -v "$PWD":/data -w /data ghcr.io/felixkrueger/trimgalore:latest trim_galore input.fastq.gz

The image tags are documented: :latest for the latest stable, currently v2.3.0, :v2.3.0 pinned to a specific release, :beta for the latest prerelease, which is only set during an active beta cycle, and :dev for every push to the dev branch. Prebuilt binaries for Linux on x86_64 and aarch64 and for macOS on Apple Silicon are on the Releases page, and the documentation points Intel Mac users at cargo install or the Docker amd64 image.

The requirement in the Cargo.toml is rust-version 1.88, edition 2024, and the package licence is GPL-3.0-only.

Running it: the same commands, plus a few new ones

The usage section is the old usage section, which is the point. Single-end and paired-end look the same as they always did:

bash
# Single-end
trim_galore input.fastq.gz

# Paired-end
trim_galore --paired file_R1.fastq.gz file_R2.fastq.gz

Parallel processing is the recommended shape for large files, and the documentation is candid about where the speedup stops:

bash
# Parallel processing (recommended for large files)
# Near-linear speedup up to ~8 cores on v2.2.0; beyond that the
# gzip-output I/O on the storage layer typically becomes binding.
trim_galore --cores 8 --paired file_R1.fastq.gz file_R2.fastq.gz

The thread model behind --cores N is N workers plus 2 decompressors plus 1 batcher plus 1 writer, so the process uses N+4 threads, and the claim is a near-linear speedup up to --cores 8 for paired-end runs, after which gzip output I/O becomes the limit.

The other modes:

bash
# RRBS mode
trim_galore --rrbs --paired file_R1.fastq.gz file_R2.fastq.gz

# Run FastQC on trimmed output
trim_galore --fastqc input.fastq.gz

And uBAM input works without a flag, because the format is auto-detected by content from the BAM magic in the decompressed payload, with the paired case taking R1 and R2 from the FREAD1 and FREAD2 flags. The paired-end handling in general is single-pass processing of both reads with automatic pair validation.

The bundled FastQC, MultiQC reports and clumpify compression

Two integrations are worth separating, because one is a replacement and the other is an optimisation.

FastQC integration is optional and post-trimming. The reports are built in via the bundled fastqc-rust library and produce FastQC 0.12.1-compatible HTML and ZIP outputs without requiring Java or an external fastqc on the path. The Dockerfile makes the point: FastQC is now built into the trim_galore binary itself, so no Java runtime, no FastQC tarball and no perl, and the runtime image only installs procps and ca-certificates.

The pinning behind that is careful. The Cargo.toml pins fastqc-rust to the exact version 1.0.1, with a comment that the crate was brand new, published 2026-04-26, so upstream bumps should be treated as deliberate test events. The comment also records that v1.0.1 fixed percentage precision in the Overrepresented sequences section and restored byte identity to Java FastQC 0.12.1 for that section. If you have a pipeline that compares FastQC numbers against a reference, that exact pin is what makes the comparison meaningful.

The trimming reports themselves parse cleanly in MultiQC dashboards, in both text and JSON.

Clumpify compression is opt-in with --clumpify and arrived in v2.2. It reorders reads by canonical 16-mer minimiser so that similar reads share gzip dictionary windows, and combined with --compression 1-9 it shrinks output by 15 to 55 percent on fragment-clustered data such as ATAC, Ribo, RRBS, RNA-seq and MiSeq amplicons.

And here is the caveat worth reading twice: coverage-diverse data regresses, with WGBS PE and scRNA-seq R2 given as examples, and the documentation points at a per-data-type guidance page rather than pretending the feature is universally good.

The multiome passthrough and the demultiplexer

The passthrough option is the most specialised feature and the one with the clearest use case.

The --passthrough <FILE> option carries a third FASTQ, typically the I1 or I2 cell-barcode read, untrimmed but in lockstep with R1 and R2. It is designed for 10X Multiome ATAC-seq libraries with modified ATAC adapters that Cellranger Arc cannot detect, so you trim R1 and R2 against your own -a or -a2 while keeping the barcode read aligned in a single invocation.

The consistency mechanism matters. Records dropped by length, quality or N filters cascade to the passthrough output, and a per-record three-way header sync check catches mid-file truncation or desync loudly. That is a good design for a feature whose failure mode would otherwise be a silently mismatched barcode file, which is the kind of error that only shows up weeks later in a single cell's data.

Demultiplexing is also listed, as 3' inline barcode demultiplexing.

There is one more piece of the compatibility story that the Rust rewrite had to reproduce. The v0.6.x Trim Galore was built on top of cutadapt, and the justfile shows that the validate target requires cutadapt, conda and a Perl Trim Galore on the PATH, and the file notes that without those only just lint test is portable. So the project keeps a Perl Trim Galore and cutadapt around for validation work, which is a good indicator of how the project itself treats the migration: the old implementation is still the oracle.

Where Trim Galore is the wrong tool

The first limit is that this is a trimming tool, not a pipeline. It removes adapters and low quality bases and it does not align, assemble or quantify. If your problem is that you need reads aligned to a reference, you need a different program and Trim Galore is a preprocessing step in front of it.

The second is the clumpify regression. The documentation says plainly that coverage-diverse data regresses under clumpify compression, with WGBS PE and scRNA-seq R2 named. So the compression win is real for clustered libraries and a liability for others, and the guidance is per data type, which means you have to know your data type before you enable it.

The third is the dev branch. The --force install from the dev branch overwrites an existing binary, which is exactly the kind of thing that should not happen on a production analysis server, and the :dev and :beta Docker tags move without notice.

The fourth is that the migration is not free even though the CLI is unchanged. Same command line and same report format means a pipeline that runs will not tell you whether the trimming decisions are the same. The documentation points at benchmarks and migration notes, which means the difference is in behaviour rather than interface, and the only way to know is to diff the reports on your own data.

Compare that with calling cutadapt directly. The difference in approach is that cutadapt gives you the primitive operations and the adapter sequences, while Trim Galore wraps them in a convention, with the auto-detection, the RRBS handling, the poly-G rules and the paired validation already decided for you. That convenience is why it is the default in so many pipelines, and it is also why a project that needs different trimming behaviour, or needs to see exactly what was cut and why, may find the wrapper is in the way.

Licence, development practice and the cost of switching

Trim Galore is released under the GPL-3.0-only licence, with the text in the LICENSE file at the repository root, and the package manifest repeats the identifier. The strong copyleft terms mean that distributing a modified version, or a binary that bundles it, carries the corresponding source obligation. That is the normal shape for a scientific tool, and anyone shipping a commercial analysis pipeline should read the LICENSE file and take their own advice on it.

The development practice is unusually disciplined and worth reading as a signal about the project. The justfile at the repository root is a local CI parity harness, so that just runs the same checks CI runs on every push, in the same order, with individual targets for each check. The default target is ci, which is fmt clippy test test-release, and the file prints a confirmation when they all pass.

Each target maps to a CI job. fmt runs cargo fmt --all with --check, fmt-fix applies the changes. clippy runs cargo clippy with --all-targets --release and -D warnings, so warnings are errors. test runs cargo test in the debug profile and test-release runs it again in the release profile, which catches the class of bug that only appears with optimisations on.

There is a version target that builds the binary and runs its --version, described as a provenance and git-hash check, and a reproduce target that builds twice under the same SOURCE_DATE_EPOCH and diffs the binaries, mirroring the reproducibility job in CI. For a tool whose output goes into a published paper, having a reproducible build is the difference between rerunning an analysis and trusting a result.

On cadence, the releases are v2.1.0 on 2026-05-04, v2.2.0 on 2026-05-07 and v2.3.0 on 2026-07-07, and the repository is not archived with the last push on 2026-10-21, so the tree is current.

What to do before you switch is a concrete sequence. Run one real paired-end library through the Perl Trim Galore and through the Rust binary with the same arguments, and diff the trimming reports. Decide whether to keep the Perl version available, since the project's own validate target expects it on the PATH. And read the clumpify page for your data type before you turn that flag on.

Editorial conclusion

Trim Galore v2 fits a sequencing pipeline that has to keep working with the same command lines and the same output files it had with the Perl version, and which now needs poly-G handling, a bundled FastQC or a Docker image that does not need Java. It does not fit a team that needs the very latest unreleased behaviour in production, since the dev branch build is explicitly a development install. Before you switch, run the same input through the old and new binaries and diff the trimming reports, decide whether to keep the Perl version on the path for the validation targets, and check the clumpify guidance for your data type, because the documentation states plainly that coverage-diverse data regresses under it.

Frequently asked questions

What is the difference between Trim Galore v2 and the old Perl scripts?

Trim Galore v2.0 is a faithful Rust rewrite, a single binary with zero external dependencies, designed as a drop-in replacement for the v0.6.x scripts with the same CLI, same output filenames and same report format. It adds poly-G auto-detection and trimming for 2-colour instruments, a generic poly-A trimmer, per-pair adapter auto-detection and cleaner multi-adapter invocation.

How do I install Trim Galore?

Four routes are documented: cargo install trim-galore from crates.io with Rust 1.88 or newer, conda install -c bioconda trim-galore, building from source with cargo build --release which puts the binary at target/release/trim_galore, and a Docker image from ghcr.io/felixkrueger/trimgalore with amd64 and arm64 support.

Does Trim Galore v2 still need Java or an external FastQC?

No. The FastQC integration is built into the binary through the bundled fastqc-rust library, producing FastQC 0.12.1-compatible HTML and ZIP outputs without Java or an external fastqc on the path. The crate is pinned to exactly version 1.0.1, and the trimming reports also parse cleanly in MultiQC dashboards.

What does the --cores option do and when does it stop helping?

It runs trimming and gzip compression in worker threads under an N+4 thread model, N workers plus 2 decompressors plus 1 batcher plus 1 writer. The speedup is near-linear up to --cores 8 for paired-end runs, and beyond that the gzip output I/O on the storage layer typically becomes the limiting factor.

What is the clumpify option for and when should I avoid it?

The opt-in --clumpify reorders reads by canonical 16-mer minimiser so similar reads share gzip dictionary windows, shrinking output by 15 to 55 percent on fragment-clustered data such as ATAC, Ribo, RRBS, RNA-seq and MiSeq amplicons. Coverage-diverse data regresses, with WGBS PE and scRNA-seq R2 given as examples, and the documentation points at per-data-type guidance.

What licence does Trim Galore use?

Trim Galore is released under the GPL-3.0-only licence, with the terms in the LICENSE file at the repository root. The current version is v2.3.0, released on 2026-07-07.

Official sources

  1. FelixKrueger/TrimGalore on GitHub
  2. License: GPL-3.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/felixkrueger-trimgalore.svg)](https://hysenlabs.com/projects/felixkrueger-trimgalore)

Was this useful?