Model or dataset
generatebio/chroma avatar
generatebio/chroma

Chroma: protein design as a programmable problem

A generative model for programmable protein design

836 stars113 forksPythonApache-2.0

At a glance

What is it?
Chroma is a generative model that designs proteins programmatically, by expressing constraints as composable conditioners and sampling all-atom structures from them. It runs diffusion modelling with equivariant graph neural networks and conditional random fields, and it exposes a single design-time parameter that trades exact backbone matching for tolerance of small deviations.
Who is it for?
Adopt Chroma if you are doing computational protein design and want the constraint specification to be code rather than a hand-tuned objective function, because the conditioner composition model is the contribution and it is genuinely programmable, with an API for your own conditioners. Do not treat a generated structure as a validated result, because the paper's own validation covers some early designs, and the pipeline produces candidates rather than demonstrated function.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

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

Editorial analysis

The problem is written as code

Chroma is a generative model for designing proteins programmatically, and the pitch is that protein space is complex and hard to search, so the design problem should be expressed in terms of composable building blocks, the conditioners, from which diverse all-atom protein structures can be automatically generated.

That framing is the whole idea. A traditional protein design pipeline optimises a score: fold the sequence into the target backbone, run a force field, keep the best of a few thousand attempts. The constraint is written in the energy function, so changing the objective means rewriting the energy function. In Chroma the constraint is a conditioner, and conditioners compose, so a design problem is assembled from pieces rather than encoded in a scoring function.

The conditioners that ship with the project cover substructure, symmetry, shape, and neural network predictions of some protein classes and annotations, and there is an API for creating your own conditioners in a few lines of code. That last point is what makes the project usable beyond the demonstrations: the intent is that you write your own constraint, not that you search for one that happens to exist.

Chroma is a joint model of structure and sequence, which means it also covers the ordinary modelling tasks that a biologist would want: generating sequences given backbones, packing side chains, and scoring designs. The model outputs Protein objects representing the all-atom structures of protein systems, and those can be loaded to and from disk in PDB or mmCIF formats, so the output goes straight into the tools the rest of the field already uses.

Diffusion, equivariant graphs and conditional random fields

Internally, Chroma uses diffusion modelling, equivariant graph neural networks, and conditional random fields, and the README makes a performance claim worth repeating: it samples all-atom structures with a complexity that is sub-quadratic in the number of residues, and it can generate large complexes in a few minutes on a commodity GPU.

The sub-quadratic part is the one that matters for the field. A complex is a set of chains, and a naive representation of a multi-chain structure has cost that grows with the square of the residue count, which is exactly the regime where design work becomes unaffordable. An equivariant graph network handles the geometry directly, with the structure of the protein as a graph whose symmetries the network respects, so a rotation of the input is a rotation of the output rather than something the model has to learn.

The conditional random fields come in because the diffusion model has to produce something that is physically coherent rather than merely plausible, and a factor graph over the residues is a natural way to express that coherence during sampling.

The work was published as Illuminating protein space with a programmable generative model in Nature in 2023, with a digital object identifier, and the README notes that the paper includes biophysical and crystallographic validation of some early designs. That last qualifier matters, and the README's own word is some: the validation covers a subset of the designs, not all of them.

One sampling entry point, three cases

Chroma.sample() is the unified entry point for both unconditional and conditional design, and the README walks through the three cases with the code for each.

The simplest is an unconditional monomer, where no conditioners are specified and the model samples a simple 200-amino acid monomeric protein:

python
from chroma import Chroma

chroma = Chroma()
protein = chroma.sample(chain_lengths=[200])

protein.to("sample.cif")
display(protein)

A complex is the same call with more than one chain length, so chain_lengths=[100, 200] gives a two-chain complex.

A conditional design adds a conditioner and the sampling hyperparameters. The README's example is a C3-symmetric homo-trimer with 100 residues per monomer:

python
from chroma import Chroma, conditioners

chroma = Chroma()
conditioner = conditioners.SymmetryConditioner(G="C_3", num_chain_neighbors=2)
protein = chroma.sample(
    chain_lengths=[100],
    conditioner=conditioner,
    langevin_factor=8,
    inverse_temperature=8,
    sde_func="langevin",
    potts_symmetry_order=conditioner.potts_symmetry_order)

protein.to("sample-C3.cif")

The hyperparameters are the sampling dynamics, with the langevin function named explicitly, and the symmetry order is read from the conditioner rather than restated, which is a small example of the composition idea working in practice.

The property that makes the design system scale is stated in one line: because compositions of conditioners are conditioners, even relatively complex design problems can follow this basic usage pattern. You stack the constraints and the composition is still a conditioner.

The design_t parameter, and why it is not a detail

The most interesting part of the README for a practitioner is the design-time parameter, and it is the one place where the project argues with its own published results.

Chroma is a joint model of sequence and structure that uses a common graph neural network base architecture to parameterise both backbone generation and conditional sequence and side chain generation. The sequence and side chain decoders are diffusion-aware in the sense that they have been trained to predict sequence and side chain not just for natural structures at diffusion time t equal to zero, but also on noisy structures at all diffusion times. The consequence is that the t hyperparameter of the design network provides a tunable trade-off: how much the model attempts to design the backbone exactly as specified, at t equal to zero, versus designing within a small neighbourhood of nearby backbone conformations, at t equal to half.

And here is the tension. All the results presented in the publication were done with exact design at t equal to zero, but the authors found that design at times near t equal to half frequently improves one-shot refolding while incurring only minor, often angstrom-scale, relaxation adjustments to the target backbone. On a set of 50,000 unconditional backbones analysed in the paper, the comparison shows very large improvements in refolding across both AlphaFold and ESMFold, and the improvement stratifies across protein length, percent helicity, and similarity to a known structure.

The parameter is set through design_t in both Chroma.sample and Chroma.design. The README says t equal to half produces highly tolerant refolding results and is therefore the default setting, while t equal to zero may be more appropriate for experimentally precise structures, and values in between may provide a useful trade-off between the two regimes.

So the default is not the setting the paper used. That is worth knowing before you read a benchmark table and assume it applies to the configuration you will run.

Weights behind a key, and notebooks to start from

The first note in the getting started section is a constraint: an API key is required to download and use the pretrained model weights, and it can be obtained from the address given in the README. The code is open, the weights are gated.

For a project that distributes a generative model, that is a common arrangement, and it has a practical consequence for anyone evaluating it: you need the key before you can run the examples, so the Colab notebooks are the fastest route in.

Three notebooks are provided, and each covers a different depth. The Chroma Quickstart is a graphical notebook demonstrating unconditional and conditional generation of proteins. The Chroma API Tutorial is a code notebook demonstrating protein input and output, sampling, and design configuration directly in Python. The Chroma Conditioner API Tutorial is a deeper dive under the hood for implementing new conditioners.

That last one is the notebook to read if you want to extend the system, because the conditioner API is where the composability claim either holds up or does not. The conditioner's own properties are used in the sampling call, as the symmetry example shows, which suggests a conditioner is a first-class object with state rather than a flag.

Installation, versioning and the packaging

The PyPI package is installed with a single command, pip install generate-chroma, and the README also gives the route from GitHub, which is a clone followed by an editable install.

The setup.py is small and tells you how the project handles the two things that usually go wrong in a research package. The install requirements are read out of requirements.txt, with inline comments stripped, so the dependency list lives in one readable file rather than in the setup script. And the version is read out of the package source, from a __version__ line in chroma/__init__.py, with a fallback error if that line cannot be found, which means the version and the code cannot drift apart.

There is a small piece of release automation on top of that. During continuous integration, if the branch is develop, the version gets a -dev suffix and a unix timestamp appended, so a build from the development branch is always distinguishable from a release. That is a small thing, and it is the kind of small thing that saves an argument about which build somebody is running.

The top-level listing is conventional for the project: the chroma/ package, notebooks/ for the Colab examples, tests/, assets/ for the images the README embeds, a Dockerfile, a requirements.txt, a setup.py and a CONTRIBUTING.md.

The dependency set and the container are both dated

The requirements file is short and mixes scientific computing with the model itself: nglview pinned at 3.0.8 for the interactive structure viewer, numpy, pandas, Pillow, pytest, Requests, scikit-learn pinned at 1.1.2, scipy, torch, tqdm and transformers pinned at 4.24.0.

The pins on scikit-learn and transformers are the interesting ones, because those are the packages most likely to have moved on. A 1.1.2 scikit-learn and a 4.24.0 transformers are both well behind current releases, which means the environment is reproducible but old, and an upgrade is a piece of work rather than a version bump.

The Dockerfile is older still. It is based on the NVIDIA CUDA 11.3.1 development image for Ubuntu 20.04, installs the usual build toolchain and image libraries, downloads Miniconda, creates a conda environment with Python 3.9.7, and installs torch 1.12.1 with the cu113 build from the PyTorch index. The package is then installed into that environment and the environment's bin directory is put on the path.

None of that makes the container unusable, and for reproducing the published work it is arguably the right thing, since the environment is the one the results were computed in. But for a new deployment, expect to rebuild the environment against a current CUDA base image and a current torch, and treat that as a task with its own risks, because the model code and a two-year-old torch release are not guaranteed to move together.

The repository as a whole is at Apache 2.0, with the licence text in a LICENSE.txt file, and the last push was on 2026-10-13.

Editorial conclusion

Adopt Chroma if you are doing computational protein design and want the constraint specification to be code rather than a hand-tuned objective function, because the conditioner composition model is the contribution and it is genuinely programmable, with an API for your own conditioners. Do not treat a generated structure as a validated result, because the paper's own validation covers some early designs, and the pipeline produces candidates rather than demonstrated function. Before you use it, note that the pretrained weights need an API key, that the packaged environment is old enough to be awkward, with an older CUDA base image and pinned versions of torch and scikit-learn, and that the design-time parameter is the setting you should be sweeping rather than accepting the default.

Frequently asked questions

What is Chroma and what does it generate?

A generative model that designs proteins programmatically. Design problems are expressed as composable conditioners, and all-atom protein structures are sampled from them. Because it is a joint model of structure and sequence, it also handles the ordinary tasks of generating sequences given backbones, packing side chains and scoring designs.

How do I install Chroma and get the model weights?

Install the package with pip install generate-chroma, or clone the repository and install it in editable mode. The pretrained weights are gated: an API key is required to download and use them, and the README links where to obtain it. The Colab notebooks are the quickest way to run the examples in a browser.

What is the design_t parameter in Chroma?

It is the diffusion time of the design network, set through the design_t parameter in Chroma.sample and Chroma.design. It trades exact matching of the target backbone at t equal to zero for designing within a small neighbourhood of nearby conformations near t equal to half, and the README says values near half frequently improve one-shot refolding while causing only minor relaxation adjustments, which is why half is the default.

Can I add my own constraints to Chroma?

Yes. The project provides an API for creating your own conditioners in a few lines of code, and the shipped conditioners cover substructure, symmetry, shape and neural network predictions of some protein classes and annotations. Because compositions of conditioners are themselves conditioners, a new one slots into the same sampling call.

Official sources

  1. generatebio/chroma on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
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/generatebio-chroma.svg)](https://hysenlabs.com/projects/generatebio-chroma)

Was this useful?