A small, focused Python library + CLI for protein sequence design built on two open ESM-family models:
- ESMC (EvolutionaryScale) — per-sequence likelihood + embeddings.
- ESMFold (Meta) — single-sequence structure prediction with per-residue pLDDT.
The pipeline is a classic score → fold → rank design loop:
WT sequence
│
▼
single-point variants ──► ESMC pseudo-log-likelihood ──► keep top-K by PLL
│
▼
ESMFold structure
│
▼
rank by (PLL, mean pLDDT) ──► CSV + PDBs
A reusable scaffold for "design a few thousand candidates → keep the best-scoring handful → fold the survivors → rank by structural confidence" that does not pull in the full nf-core / RFdiffusion machinery. Useful as a starting point for binder ideation, stability mutagenesis, or any task where the search space is small enough that brute-force scoring is cheaper than generative sampling.
# CPU-only (CLI + variant generation + IO + tests)
pip install -e .
# With model inference (PyTorch + ESM stack; needs a CUDA GPU for ESMFold)
pip install -e ".[models]"The models extra installs torch, transformers, and the
esm package from EvolutionaryScale. ESMFold needs ~16 GB GPU memory for
sequences up to ~500 residues; ESMC-300M runs in <2 GB.
Score every single-point variant of a wild-type sequence and rank the top 16:
esm-design design \
--wt examples/example.fa \
--out-dir results/ \
--top-k 16 \
--fold-top 5 \
--device cudaOutputs:
results/
├── variants.csv # all variants + PLL
├── ranked.csv # top-K by PLL, plus mean pLDDT for fold-top
└── pdbs/
├── rank01_V42L.pdb
├── rank02_S88T.pdb
└── ...
| Command | What it does |
|---|---|
esm-design score --fasta IN.fa --out scores.csv |
Run ESMC on each sequence, write pseudo-log-likelihood + length to CSV. |
esm-design fold --fasta IN.fa --out-dir pdbs/ |
Run ESMFold on each sequence, write <name>.pdb + summary CSV with mean pLDDT. |
esm-design design --wt WT.fa --out-dir results/ |
Full loop: generate single-point variants, score with ESMC, fold top survivors, rank. |
esm-design mutate --wt WT.fa --out variants.fa --mode all|alanine |
Just generate variants (no inference). |
All commands accept --device {cpu,cuda,mps,auto} (default auto) and
--model-esmc / --model-esmfold overrides.
from esm_design.mutate import single_point_variants, apply_variant
from esm_design.score import ESMCScorer
from esm_design.fold import ESMFolder
wt = "MKAILVVLLYTFTSCQAEHTDCTSDESEMK..."
variants = [(p, wt[p], aa) for p, wt_aa, aa in single_point_variants(wt)]
scorer = ESMCScorer(device="cuda")
seqs = [apply_variant(wt, p, aa) for p, _, aa in variants]
plls = scorer.score(seqs)
folder = ESMFolder(device="cuda")
result = folder.fold(seqs[0], name="variant_001")
print(result["mean_plddt"], len(result["pdb"]))esm-design/
├── src/esm_design/
│ ├── cli.py CLI dispatch (argparse)
│ ├── mutate.py variant generation
│ ├── score.py ESMC scoring (lazy-imports esm)
│ ├── fold.py ESMFold structure prediction (lazy-imports transformers)
│ ├── design.py end-to-end design loop
│ └── io.py FASTA + CSV helpers
├── tests/ CPU-only tests (model code is stubbed)
├── examples/ tiny example FASTA + shell driver
└── .github/workflows/ ruff + pytest CI
pip install -e ".[dev]"
ruff check .
pytest -qCI runs ruff + pytest on CPU and does not download any model weights — tests cover IO, variant generation, and CLI argument parsing.
| Default | Override | Notes |
|---|---|---|
| ESMC | esmc_300m |
Smallest open ESMC checkpoint; ~600 MB. |
| ESMFold | facebook/esmfold_v1 |
Meta's open ESMFold; ~6 GB. |
Larger ESMC checkpoints (esmc_600m, esmc_6b) are drop-in via --model-esmc.
MIT — see LICENSE.