FASTQ Quality Control & Trimming Decisions
Run quality control on raw sequencing reads, interpret the report, and make
an evidence-based decision about whether to trim — using real local
command-line tools (FastQC, MultiQC, fastp, Cutadapt, seqkit).
Honesty contract (read first)
This skill drives real binaries. It must never fabricate QC numbers.
- Preflight before anything. Check whether the required tools are on
PATH. If a required tool is missing, emit the install plan and STOP.
Do not estimate, guess, or describe hypothetical QC results.
- Never auto-trim. Trimming is a decision. QC-only is the default.
Only trim after inspecting adapter content / per-base quality, and only
when the user has confirmed
--mode trim.
- Never overwrite raw FASTQs. All outputs go to a separate
--workdir.
The input directory is read-only. Trimmed reads are written as NEW files.
- If you cannot run, say so. "FastQC is not installed; here is the
install plan" is the correct answer — not a made-up PASS/FAIL table.
When to use vs. not
Use this skill when the user wants to:
- Run FastQC / fastp QC on one or more FASTQ (
.fastq, .fq, .gz) files
- Interpret a FastQC report (per-base quality, adapter content, etc.)
- Decide whether adapter or quality trimming is needed before downstream work
- Summarize many samples into one MultiQC report
- Count reads, get length/GC stats, or subsample with seqkit
- Trim adapters/low-quality bases with fastp or Cutadapt (explicitly)
Do NOT use this skill for (route elsewhere):
- Differential expression / DEG / fold-change analysis ->
tooluniverse-rnaseq-deseq2
- Read alignment, coverage depth, samtools, BWA ->
tooluniverse-sequence-analysis
- Variant calling, VCF, VAF, mutation analysis ->
tooluniverse-variant-analysis
- Single-cell / scRNA QC (per-cell metrics, scanpy) ->
tooluniverse-single-cell
Essential inputs to confirm
Before running, confirm with the user (ask if unstated):
- FASTQ paths — exact path(s). One file = single-end; an R1+R2 pair =
paired-end (e.g.
*_R1.fastq.gz / *_R2.fastq.gz).
- QC-only or trim? Default is QC-only. Only trim on explicit request.
- Known adapters / primers? Standard Illumina adapters are auto-detected
by fastp; amplicon/primer sequences usually need explicit Cutadapt removal.
- Organism — only needed if a contamination / over-representation screen
is requested (needs a reference; see Limitations).
- Output directory — a
--workdir SEPARATE from the input folder.
- Read provenance — are these raw, already-trimmed, or UMI-tagged reads?
Already-trimmed reads should NOT be trimmed again; UMIs must be handled
before trimming or you corrupt the UMI.
Preflight (do this first, every time)
The bundled script preflights for you, but the decision logic is:
import shutil
for tool in ("fastqc", "fastp", "seqkit"):
print(tool, shutil.which(tool) or "MISSING")
command -v fastqc / shutil.which("fastqc") returning nothing means the
tool is absent. If a required tool (FastQC for QC; FastQC+fastp for trim)
is missing, emit:
mamba install -c bioconda -c conda-forge fastqc fastp seqkit multiqc
# or
conda install -c bioconda -c conda-forge fastqc fastp seqkit multiqc
and stop. Do not proceed to fabricate output.
Tool roles
| Tool |
Role |
Install (bioconda) |
| FastQC |
Per-file raw read QC; produces the module PASS/WARN/FAIL report |
fastqc |
| MultiQC |
Aggregates many FastQC (and fastp) reports into one summary |
multiqc |
| fastp |
All-in-one QC + adapter + quality trimming (fast, auto-detect) |
fastp |
| Cutadapt |
Explicit, precise adapter/primer removal (amplicons, custom) |
cutadapt |
| seqkit |
Read counts, length/GC stats, subsampling |
seqkit |
Rule of thumb: FastQC to diagnose, fastp to fix general adapter/quality,
Cutadapt to fix a known primer/adapter precisely, seqkit to count/stat.
Bundled orchestration script
scripts/run_fastq_qc.py does the preflight + run-if-available + plan-if-missing
flow, with workspace isolation built in.
# QC only (default) — never modifies reads
python scripts/run_fastq_qc.py \
--fastq reads/sample_R1.fastq.gz reads/sample_R2.fastq.gz \
--workdir /tmp/fastq_qc_run
# QC + trim (explicit) — fastp writes NEW trimmed files into --workdir
python scripts/run_fastq_qc.py \
--fastq reads/sample_R1.fastq.gz reads/sample_R2.fastq.gz \
--workdir /tmp/fastq_qc_run \
--mode trim
Behavior:
- Preflights FastQC (+ fastp in trim mode) and seqkit. If a required
tool is missing it prints the install plan and exits 0 — no fabricated QC.
- Runs FastQC (always) + seqkit stats (if present) into
--workdir.
- In
--mode trim, runs fastp writing *.trimmed.fastq.gz into
--workdir/trimmed/ — raw inputs are never touched.
- Refuses to run if
--workdir equals an input directory (overwrite guard).
For a project-level summary after FastQC, run MultiQC over the workdir:
multiqc /tmp/fastq_qc_run -o /tmp/fastq_qc_run/multiqc
INTERPRETATION — FastQC module -> meaning -> action
This table is the core value-add. Map each FastQC module to what PASS/WARN/FAIL
means and what to actually do. (See references/fastqc_interpretation.md for the
long form with thresholds and worked cases.)
| FastQC module |
Typical PASS |
WARN / FAIL means |
Suggested action |
| Per base sequence quality |
All positions Q>=28 |
3' tail drops below Q20-Q28 (common, esp. R2) |
Quality-trim 3' (fastp -q/sliding window). Proceed if only the last few bases dip. |
| Per base N content |
Near 0% N |
Spike of N at a position = sequencer/base-call problem |
Investigate: cycle-specific issue; consider hard-trim that position or re-sequence. |
| Adapter content |
Flat, no adapter ramp |
Rising adapter % toward 3' end = read-through into adapter |
Trim adapters (fastp auto-detect, or Cutadapt with the known adapter). |
| Overrepresented sequences |
None / <0.1% |
A sequence is a large fraction: adapter, primer-dimer, rRNA, or low-complexity |
Investigate the hit (BLAST it). If adapter/primer -> trim. If biology (rRNA/highly-expressed) -> proceed. |
| Sequence Duplication Levels |
Low (diverse library) |
High duplication = PCR over-amplification OR expected (amplicon/RNA-seq) |
Investigate, usually proceed. Do NOT dedup blindly — expected high in amplicon/targeted/RNA-seq. Mark-duplicates belongs post-alignment, not here. |
| Per sequence GC content |
Single peak at expected GC |
Bimodal / shifted peak = contamination or mixed species |
Investigate contamination (needs a reference screen; see Limitations). Not fixed by trimming. |
| Per base sequence content |
Flat after first ~10 bp |
Bias in first bases (random-hexamer priming) or adapter |
Random-priming bias: usually proceed (expected in RNA-seq). Persistent bias at 3' -> adapter -> trim. |
| Sequence Length Distribution |
Single length (raw) |
Multiple lengths AFTER trimming is normal; before trimming may indicate mixed input |
Usually proceed; only a concern on supposedly-raw uniform-length data. |
Decision summary for "do I need to trim?"
- Adapter content FAIL/WARN with a 3' adapter ramp -> yes, adapter-trim.
- Per-base quality FAIL at the 3' tail -> yes, quality-trim that tail.
- Overrepresented = adapter/primer-dimer -> yes, trim; overrepresented =
biology (rRNA, abundant transcript) -> no, proceed.
- High duplication / GC anomaly / N-spike -> investigate, not a trimming fix.
- Everything PASS -> proceed without trimming.
Workflow
- Confirm inputs (paths, pairing, mode, adapters, provenance).
- Preflight tools. If missing -> install plan, STOP.
- Run QC (
--mode qc): FastQC + seqkit -> read the report.
- Interpret each flagged module with the table above.
- Decide trim vs investigate vs proceed. State the decision and why.
- (If trimming chosen) run
--mode trim (fastp) or Cutadapt for precise
primer removal; re-run FastQC on the trimmed output to confirm the fix.
- (Optional) MultiQC for a multi-sample summary.
- Report: per-module status, the trim decision + rationale, and the exact
commands run. Never report numbers a tool did not actually produce.
Limitations (honest)
- Requires local binaries. FastQC/fastp/seqkit/Cutadapt/MultiQC must be
installed (bioconda). This is not a cloud service; with no tools installed
the skill can only emit an install plan, not QC results.
- Large files. Whole-lane FASTQs can be many GB; FastQC/fastp are
single-pass and memory-light but still I/O-bound. Use seqkit
sample to
subsample for a quick look on huge files.
- Contamination / cross-species screening is NOT included by default. GC
anomalies and "is this the right organism" need a reference index
(e.g. FastQ Screen + bowtie2 indexes, or Kraken2) — extra setup beyond this
skill's bundled tools.
- No deduplication of raw reads. PCR-duplicate removal is an alignment-stage
decision (Picard/samtools markdup); FastQC duplication is diagnostic only.
- UMI-aware trimming needs UMI extraction first (umi_tools); naive trimming
corrupts UMIs.
Completeness checklist
References
references/fastqc_interpretation.md — full module-by-module thresholds + cases
references/tools_and_install.md — install commands, tool flags, command recipes
references/trimming_decisions.md — when/how to trim (fastp vs Cutadapt), pitfalls
1---
2
3name: tooluniverse-fastq-qc
4description: "FASTQ quality control and adapter/quality-trimming decisions with local NGS tools — run FastQC on raw reads, summarize a project with MultiQC, interpret per-base sequence quality, per-base N content, adapter content, overrepresented sequences, sequence duplication and GC content, and decide whether (and how) to trim with fastp / Cutadapt before downstream analysis. seqkit for read counts/stats/subsampling. Use when someone asks \"run QC on my FASTQs\", \"are my reads good quality?\", \"do I need to trim adapters?\", \"interpret this FastQC report\", \"what does this WARN/FAIL mean\", \"why are overrepresented sequences flagged\", \"should I quality-trim before alignment\", \"make a MultiQC summary\", or \"clean up these reads with fastp\". NOT for differential expression / DEG analysis (use tooluniverse-rnaseq-deseq2), NOT for read alignment, coverage, or variant calling (use tooluniverse-variant-analysis / tooluniverse-sequence-analysis). Honest: shells out to real local binaries; if a tool is missing..."
5---
6
7# FASTQ Quality Control & Trimming Decisions
8
9Run quality control on raw sequencing reads, interpret the report, and make
10an evidence-based decision about whether to trim — using real local
11command-line tools (FastQC, MultiQC, fastp, Cutadapt, seqkit).
12
13## Honesty contract (read first)
14
15This skill drives **real binaries**. It must never fabricate QC numbers.
16
171. **Preflight before anything.** Check whether the required tools are on
18 PATH. If a required tool is missing, emit the install plan and STOP.
19 Do not estimate, guess, or describe hypothetical QC results.
202. **Never auto-trim.** Trimming is a *decision*. QC-only is the default.
21 Only trim after inspecting adapter content / per-base quality, and only
22 when the user has confirmed `--mode trim`.
233. **Never overwrite raw FASTQs.** All outputs go to a separate `--workdir`.
24 The input directory is read-only. Trimmed reads are written as NEW files.
254. **If you cannot run, say so.** "FastQC is not installed; here is the
26 install plan" is the correct answer — not a made-up PASS/FAIL table.
27
28## When to use vs. not
29
30**Use this skill when the user wants to:**
31- Run FastQC / fastp QC on one or more FASTQ (`.fastq`, `.fq`, `.gz`) files
32- Interpret a FastQC report (per-base quality, adapter content, etc.)
33- Decide whether adapter or quality trimming is needed before downstream work
34- Summarize many samples into one MultiQC report
35- Count reads, get length/GC stats, or subsample with seqkit
36- Trim adapters/low-quality bases with fastp or Cutadapt (explicitly)
37
38**Do NOT use this skill for (route elsewhere):**
39- Differential expression / DEG / fold-change analysis -> `tooluniverse-rnaseq-deseq2`
40- Read alignment, coverage depth, samtools, BWA -> `tooluniverse-sequence-analysis`
41- Variant calling, VCF, VAF, mutation analysis -> `tooluniverse-variant-analysis`
42- Single-cell / scRNA QC (per-cell metrics, scanpy) -> `tooluniverse-single-cell`
43
44## Essential inputs to confirm
45
46Before running, confirm with the user (ask if unstated):
47
481. **FASTQ paths** — exact path(s). One file = single-end; an R1+R2 pair =
49 paired-end (e.g. `*_R1.fastq.gz` / `*_R2.fastq.gz`).
502. **QC-only or trim?** Default is QC-only. Only trim on explicit request.
513. **Known adapters / primers?** Standard Illumina adapters are auto-detected
52 by fastp; amplicon/primer sequences usually need explicit Cutadapt removal.
534. **Organism** — only needed if a contamination / over-representation screen
54 is requested (needs a reference; see Limitations).
555. **Output directory** — a `--workdir` SEPARATE from the input folder.
566. **Read provenance** — are these raw, already-trimmed, or UMI-tagged reads?
57 Already-trimmed reads should NOT be trimmed again; UMIs must be handled
58 before trimming or you corrupt the UMI.
59
60## Preflight (do this first, every time)
61
62The bundled script preflights for you, but the decision logic is:
63
64```python
65import shutil
66for tool in ("fastqc", "fastp", "seqkit"):
67 print(tool, shutil.which(tool) or "MISSING")
68```
69
70`command -v fastqc` / `shutil.which("fastqc")` returning nothing means the
71tool is absent. If a **required** tool (FastQC for QC; FastQC+fastp for trim)
72is missing, emit:
73
74```
75mamba install -c bioconda -c conda-forge fastqc fastp seqkit multiqc
76# or
77conda install -c bioconda -c conda-forge fastqc fastp seqkit multiqc
78```
79
80and stop. Do not proceed to fabricate output.
81
82## Tool roles
83
84| Tool | Role | Install (bioconda) |
85|-----------|----------------------------------------------------------------|--------------------|
86| FastQC | Per-file raw read QC; produces the module PASS/WARN/FAIL report | `fastqc` |
87| MultiQC | Aggregates many FastQC (and fastp) reports into one summary | `multiqc` |
88| fastp | All-in-one QC + adapter + quality trimming (fast, auto-detect) | `fastp` |
89| Cutadapt | Explicit, precise adapter/primer removal (amplicons, custom) | `cutadapt` |
90| seqkit | Read counts, length/GC stats, subsampling | `seqkit` |
91
92Rule of thumb: **FastQC to diagnose, fastp to fix general adapter/quality,
93Cutadapt to fix a known primer/adapter precisely, seqkit to count/stat.**
94
95## Bundled orchestration script
96
97`scripts/run_fastq_qc.py` does the preflight + run-if-available + plan-if-missing
98flow, with workspace isolation built in.
99
100```bash
101# QC only (default) — never modifies reads
102python scripts/run_fastq_qc.py \
103 --fastq reads/sample_R1.fastq.gz reads/sample_R2.fastq.gz \
104 --workdir /tmp/fastq_qc_run
105
106# QC + trim (explicit) — fastp writes NEW trimmed files into --workdir
107python scripts/run_fastq_qc.py \
108 --fastq reads/sample_R1.fastq.gz reads/sample_R2.fastq.gz \
109 --workdir /tmp/fastq_qc_run \
110 --mode trim
111```
112
113Behavior:
114- **Preflights** FastQC (+ fastp in trim mode) and seqkit. If a required
115 tool is missing it prints the install plan and exits 0 — no fabricated QC.
116- Runs **FastQC** (always) + **seqkit stats** (if present) into `--workdir`.
117- In `--mode trim`, runs **fastp** writing `*.trimmed.fastq.gz` into
118 `--workdir/trimmed/` — raw inputs are never touched.
119- **Refuses** to run if `--workdir` equals an input directory (overwrite guard).
120
121For a project-level summary after FastQC, run MultiQC over the workdir:
122
123```bash
124multiqc /tmp/fastq_qc_run -o /tmp/fastq_qc_run/multiqc
125```
126
127## INTERPRETATION — FastQC module -> meaning -> action
128
129This table is the core value-add. Map each FastQC module to what PASS/WARN/FAIL
130means and what to actually do. (See `references/fastqc_interpretation.md` for the
131long form with thresholds and worked cases.)
132
133| FastQC module | Typical PASS | WARN / FAIL means | Suggested action |
134|------------------------------|---------------------------|----------------------------------------------------------------|------------------|
135| Per base sequence quality | All positions Q>=28 | 3' tail drops below Q20-Q28 (common, esp. R2) | **Quality-trim** 3' (fastp `-q`/sliding window). Proceed if only the last few bases dip. |
136| Per base N content | Near 0% N | Spike of N at a position = sequencer/base-call problem | **Investigate**: cycle-specific issue; consider hard-trim that position or re-sequence. |
137| Adapter content | Flat, no adapter ramp | Rising adapter % toward 3' end = read-through into adapter | **Trim adapters** (fastp auto-detect, or Cutadapt with the known adapter). |
138| Overrepresented sequences | None / <0.1% | A sequence is a large fraction: adapter, primer-dimer, rRNA, or low-complexity | **Investigate** the hit (BLAST it). If adapter/primer -> trim. If biology (rRNA/highly-expressed) -> proceed. |
139| Sequence Duplication Levels | Low (diverse library) | High duplication = PCR over-amplification OR expected (amplicon/RNA-seq) | **Investigate, usually proceed**. Do NOT dedup blindly — expected high in amplicon/targeted/RNA-seq. Mark-duplicates belongs post-alignment, not here. |
140| Per sequence GC content | Single peak at expected GC| Bimodal / shifted peak = contamination or mixed species | **Investigate** contamination (needs a reference screen; see Limitations). Not fixed by trimming. |
141| Per base sequence content | Flat after first ~10 bp | Bias in first bases (random-hexamer priming) or adapter | Random-priming bias: usually **proceed** (expected in RNA-seq). Persistent bias at 3' -> adapter -> trim. |
142| Sequence Length Distribution | Single length (raw) | Multiple lengths AFTER trimming is normal; before trimming may indicate mixed input | Usually **proceed**; only a concern on supposedly-raw uniform-length data. |
143
144**Decision summary for "do I need to trim?"**
145- Adapter content FAIL/WARN with a 3' adapter ramp -> **yes, adapter-trim**.
146- Per-base quality FAIL at the 3' tail -> **yes, quality-trim** that tail.
147- Overrepresented = adapter/primer-dimer -> **yes, trim**; overrepresented =
148 biology (rRNA, abundant transcript) -> **no, proceed**.
149- High duplication / GC anomaly / N-spike -> **investigate**, not a trimming fix.
150- Everything PASS -> **proceed without trimming.**
151
152## Workflow
153
1541. **Confirm inputs** (paths, pairing, mode, adapters, provenance).
1552. **Preflight** tools. If missing -> install plan, STOP.
1563. **Run QC** (`--mode qc`): FastQC + seqkit -> read the report.
1574. **Interpret** each flagged module with the table above.
1585. **Decide** trim vs investigate vs proceed. State the decision and why.
1596. **(If trimming chosen)** run `--mode trim` (fastp) or Cutadapt for precise
160 primer removal; re-run FastQC on the trimmed output to confirm the fix.
1617. **(Optional)** MultiQC for a multi-sample summary.
1628. **Report**: per-module status, the trim decision + rationale, and the exact
163 commands run. Never report numbers a tool did not actually produce.
164
165## Limitations (honest)
166
167- **Requires local binaries.** FastQC/fastp/seqkit/Cutadapt/MultiQC must be
168 installed (bioconda). This is not a cloud service; with no tools installed
169 the skill can only emit an install plan, not QC results.
170- **Large files.** Whole-lane FASTQs can be many GB; FastQC/fastp are
171 single-pass and memory-light but still I/O-bound. Use seqkit `sample` to
172 subsample for a quick look on huge files.
173- **Contamination / cross-species screening is NOT included by default.** GC
174 anomalies and "is this the right organism" need a reference index
175 (e.g. FastQ Screen + bowtie2 indexes, or Kraken2) — extra setup beyond this
176 skill's bundled tools.
177- **No deduplication of raw reads.** PCR-duplicate removal is an alignment-stage
178 decision (Picard/samtools markdup); FastQC duplication is diagnostic only.
179- **UMI-aware trimming** needs UMI extraction first (umi_tools); naive trimming
180 corrupts UMIs.
181
182## Completeness checklist
183
184- [ ] Inputs confirmed (paths, single/paired, raw vs trimmed, adapters)
185- [ ] Tools preflighted; install plan emitted if any required tool missing
186- [ ] QC run with outputs in a workdir separate from inputs (raw preserved)
187- [ ] Each flagged FastQC module interpreted (meaning + action)
188- [ ] Explicit trim/investigate/proceed decision with rationale
189- [ ] Trimming (if done) was opt-in, wrote new files, raw FASTQs untouched
190- [ ] Post-trim FastQC re-run to confirm the fix (if trimmed)
191- [ ] No QC numbers reported that a tool did not actually produce
192
193## References
194
195- `references/fastqc_interpretation.md` — full module-by-module thresholds + cases
196- `references/tools_and_install.md` — install commands, tool flags, command recipes
197- `references/trimming_decisions.md` — when/how to trim (fastp vs Cutadapt), pitfalls