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.
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.
| Feature | seqkit | seqtk |
|---|---|---|
| Language | Go | C |
Gzip input (.fq.gz, .fa.gz) | Native, no flag needed | Native, no flag needed |
| Best for | Stats, filtering, searching, format conversion, sliding windows | Subsampling, quality trimming, quick FASTQ→FASTA |
| Typical first command | seqkit stats | seqtk 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
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 3That 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.
conda create -n bu-seqtools --override-channels -c conda-forge -c bioconda seqkit seqtkBecause 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:
conda activate bu-seqtools
conda list seqkit seqtkLook 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:
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
seqkit version
seqtk 2>&1 | head -n 3seqkit 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:
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
EOFNow run the command that should be your reflex on any new sequence file:
seqkit stats toy.fastaYou 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:
seqkit stats -a reads.fastq.gzThe -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:
seqkit seq -m 15 toy.fastaReverse-complement every sequence:
seqkit seq -rp toy.fastaConvert FASTQ to FASTA (dropping quality scores), which comes up constantly when a downstream tool only accepts FASTA:
seqkit fq2fa reads.fastq.gz -o reads.fastaseqtk 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:
seqtk seq -a reads.fastq.gz > reads.fastaStep 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:
seqtk sample -s100 reads.fastq.gz 0.1 > subsample.fastqThat 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:
seqtk sample -s100 reads_R1.fastq.gz 0.1 > sub_R1.fastq
seqtk sample -s100 reads_R2.fastq.gz 0.1 > sub_R2.fastqYou 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
| Error | Fix |
|---|---|
CondaToSNonInteractiveError / Terms of Service not accepted for defaults | Do not use the defaults channel. Install with --override-channels -c conda-forge -c bioconda as shown. |
PackagesNotFoundError: ... seqkit or seqtk | The bioconda channel is missing or out of order. Pass both channels with conda-forge first. |
seqkit: command not found / seqtk: command not found | You did not activate the env. Run conda activate bu-seqtools, then confirm with which seqkit. |
seqtk sample output differs between R1 and R2 subsamples | The 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: 0 | The 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 FASTA | seqkit 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:
conda update -n bu-seqtools --override-channels -c conda-forge -c bioconda seqkit seqtkSnapshot the exact environment so a collaborator can reproduce it:
conda env export -n bu-seqtools > seqtools-env.ymlAnd when you are done experimenting, remove it cleanly:
conda remove -n bu-seqtools --allNext 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.