Back to Blog
FASTAUtilities

Install seqkit and seqtk: FASTA/FASTQ Toolkits (macOS, conda)

Install seqkit and seqtk in one conda env on Apple Silicon, then filter, subsample, convert, and get instant stats on FASTA/FASTQ files.

SSSudipta SardarJuly 20, 20269 min read
Install seqkit and seqtk: FASTA/FASTQ Toolkits (macOS, conda)

Every bioinformatics workflow eventually needs a quick answer to a boring question: how many reads are in this file, how long are they, and can I grab a random 10% of them for a test run. seqkit and seqtk are the two command-line tools that answer those questions in milliseconds instead of a slow custom script. Both are native, statically-built binaries that run at full speed on Apple Silicon, and together they cover almost everything you would otherwise reach for awk or a Biopython one-liner to do.

This guide installs both into one isolated conda environment, verifies the install, and walks through the handful of subcommands you will actually use every day: seqkit stats, seqkit seq, and seqtk sample.

What are seqkit and seqtk, and why both?

seqkit and seqtk overlap in purpose but not in feel. seqtk, written in C by Heng Li (the author of samtools and bwa), is the older, leaner of the two -- a handful of tight subcommands for sampling, trimming, and format conversion. seqkit, written in Go, is the newer, broader toolkit: dozens of subcommands covering filtering, searching, sliding windows, deduplication, and statistics, all with consistent flag naming and built-in gzip support.

In practice most people keep both around. seqtk sample is the tool everyone reaches for to subsample reads, out of sheer habit and its tiny memory footprint, while seqkit handles everything else -- especially seqkit stats, which is usually the very first command you run on a new FASTA or FASTQ file.

Featureseqkitseqtk
LanguageGoC
Gzip input (.fq.gz, .fa.gz)Native, no flag neededNative, no flag needed
Best forStats, filtering, searching, format conversion, sliding windowsSubsampling, quality trimming, quick FASTQ→FASTA
Typical first commandseqkit statsseqtk sample

Prerequisites

You need a working conda on your Mac. If you do not have one yet, start with our Miniconda on Apple Silicon guide and come back here. We also lean on the isolation habit explained in Conda environments and Bioconda channels: one environment, bioconda and conda-forge only, --override-channels so conda never touches the gated Anaconda defaults channel.

Both seqkit and seqtk are lightweight enough that it makes sense to install them together in a single shared environment rather than splitting them across two.

TL;DR: copy-paste install

bash
conda create -n bu-seqtools --override-channels -c conda-forge -c bioconda seqkit seqtk
conda activate bu-seqtools
seqkit version
seqtk 2>&1 | head -n 3

That is the whole install. The rest of this guide explains each step, shows what the subcommands do, and covers the gotchas worth knowing about.

Step 1: Create an isolated environment

Name the environment something you will recognize later, bu-seqtools works fine, and ask for both packages by their exact bioconda names, seqkit and seqtk. conda-forge is listed first so it takes priority for any shared dependency, and bioconda supplies the two tools themselves.

bash
conda create -n bu-seqtools --override-channels -c conda-forge -c bioconda seqkit seqtk

Because both packages are small, statically-linked binaries with almost no runtime dependencies, this solve and download should finish in well under a minute on a normal connection. You should see a package plan listing seqkit and seqtk as new packages, each just a few megabytes, with no large dependency chain pulled in behind them.

Apple Silicon: native arm64, no Rosetta needed

Both tools compile cleanly to arm64, and bioconda ships native osx-arm64 builds for each. You can confirm this after activating the environment:

bash
conda activate bu-seqtools
conda list seqkit seqtk

Look at the build channel string for each package; it should read something like bioconda/osx-arm64::seqkit-... and bioconda/osx-arm64::seqtk-.... You can also check the binaries themselves:

bash
file "$(which seqkit)" "$(which seqtk)"

Both should report as arm64 Mach-O executables. That matters because these tools spend their whole life doing tight loops over millions of sequence records, exactly the kind of workload where Rosetta 2's binary translation overhead is most noticeable. Go's cross-compiler produces first-class arm64 output out of the box, which is a big part of why seqkit in particular has felt "just fast" on Apple Silicon since long before most C-heavy bioinformatics tools caught up. If you ever end up with a tool that only ships osx-64 builds, the fallback is a separate Rosetta-emulated environment (CONDA_SUBDIR=osx-64 conda create ...), but neither seqkit nor seqtk should ever force you into that.

Step 2: Verify the install

bash
seqkit version
seqtk 2>&1 | head -n 3

seqkit version prints a clean version string. seqtk has no --version flag in the classic sense; running it with no arguments (redirecting stderr so head can see it) prints a short usage banner whose first line names the version. You should see something like this:

seqkit v2.x.x

Usage:   seqtk <command> <arguments>
Version: 1.x-r...

If either command prints command not found, you forgot to conda activate bu-seqtools in this shell -- activation is per-session and does not persist across new terminal tabs.

Step 3: seqkit stats -- instant file statistics

Create a tiny toy FASTA to work with:

bash
mkdir -p /tmp/seqtools_demo && cd /tmp/seqtools_demo
cat > toy.fasta << 'EOF'
>seq1 short read
ATGCATGCATGCATGCATGC
>seq2 longer read
ATGCATGCATGCATGCATGCATGCATGCATGCATGCATGC
>seq3 tiny fragment
ATGCATGC
EOF

Now run the command that should be your reflex on any new sequence file:

bash
seqkit stats toy.fasta

You should see something like:

file       format  type  num_seqs  sum_len  min_len  avg_len  max_len
toy.fasta  FASTA   DNA          3       68        8     22.7       40

One line, and you instantly know the record count, total bases, and the length distribution's extremes. Point it straight at a gzipped FASTQ from a sequencer and it works the same way, no manual decompression needed:

bash
seqkit stats -a reads.fastq.gz

The -a flag adds extended statistics -- N50, quartiles, and GC content -- which is genuinely useful for a first sanity check on a new sequencing run before you commit to a full QC pipeline.

Step 4: seqkit seq -- filter, convert, and reformat

seqkit seq is the swiss-army-knife subcommand: it reads sequences and writes them back out, optionally filtered or transformed along the way.

Keep only sequences at least 15 bp long, dropping the short fragment:

bash
seqkit seq -m 15 toy.fasta

Reverse-complement every sequence:

bash
seqkit seq -rp toy.fasta

Convert FASTQ to FASTA (dropping quality scores), which comes up constantly when a downstream tool only accepts FASTA:

bash
seqkit fq2fa reads.fastq.gz -o reads.fasta

seqtk has its own well-known one-liner for the same conversion, and it is worth knowing both since you will see it in older pipelines:

bash
seqtk seq -a reads.fastq.gz > reads.fasta

Step 5: seqtk sample -- reproducible subsampling

When you need to test a pipeline on a slice of data instead of the full run, seqtk sample is the standard tool. It uses reservoir sampling, so it never has to load the whole file into memory, and the -s seed makes the result reproducible:

bash
seqtk sample -s100 reads.fastq.gz 0.1 > subsample.fastq

That pulls roughly 10% of the reads, using seed 100. Pass the same seed to both mates of a paired-end run and seqtk will pick the identical read indices from each file, which is exactly what keeps a subsampled pair in sync:

bash
seqtk sample -s100 reads_R1.fastq.gz 0.1 > sub_R1.fastq
seqtk sample -s100 reads_R2.fastq.gz 0.1 > sub_R2.fastq

You can also pass an integer instead of a fraction, seqtk sample -s100 reads.fastq.gz 50000, to grab an exact number of reads rather than a percentage.

Common errors and fixes

ErrorFix
CondaToSNonInteractiveError / Terms of Service not accepted for defaultsDo not use the defaults channel. Install with --override-channels -c conda-forge -c bioconda as shown.
PackagesNotFoundError: ... seqkit or seqtkThe bioconda channel is missing or out of order. Pass both channels with conda-forge first.
seqkit: command not found / seqtk: command not foundYou did not activate the env. Run conda activate bu-seqtools, then confirm with which seqkit.
seqtk sample output differs between R1 and R2 subsamplesThe seed (-s) was different, or one file has more records than the other. Use the identical -s value on both mates from the same original pair.
seqkit stats runs but shows num_seqs: 0The file is empty, truncated, or the wrong format (e.g. a BAM file passed by mistake). Check with seqkit seq -n file | head.
Mixed line-wrapping widths in output FASTAseqkit seq -w 0 disables wrapping (one sequence per line); seqkit seq -w 60 forces 60-character wrapping.

Managing the environment

Update both tools in place:

bash
conda update -n bu-seqtools --override-channels -c conda-forge -c bioconda seqkit seqtk

Snapshot the exact environment so a collaborator can reproduce it:

bash
conda env export -n bu-seqtools > seqtools-env.yml

And when you are done experimenting, remove it cleanly:

bash
conda remove -n bu-seqtools --all

Next steps

With seqkit and seqtk installed, a natural next step is putting them to work in a real pipeline: use seqkit stats as your first QC checkpoint before alignment, and seqtk sample to build small test datasets while you debug a workflow. If you are heading toward transcript quantification next, see Install Salmon for RNA-seq quantification, or read Conda environments and Bioconda channels if any of the channel flags above were unfamiliar.