# Poly: a Go library for engineering organisms

> Poly is a Go package for synthetic biology work, with packages for sequence I/O, transformation, primer design, synthesis, search, sequence hashing, cloning, alphabets and randomisation. It is the part of a bioinformatics stack that wants a language built for speed, and the published releases stopped in 2024 while the repository was pushed to in 2026.

**bebop/poly** — A Go package for engineering organisms.

- Repository: https://github.com/bebop/poly
- Website: https://pkg.go.dev/github.com/bebop/poly
- Stars: 735 · Forks: 72
- Language: Go
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/bebop-poly

## A package organised by task rather than by data type

Poly is a Go package for engineering organisms, and the repository layout is the most informative thing about it because the top level directories are named after operations rather than after abstractions.

There is an io/ directory for reading and writing sequences, a transform/ directory, a primers/ directory, a synthesis/ directory, a search/ directory, a seqhash/ directory, a clone/ directory, an alphabet/ directory, a random/ directory, a fold/ directory and a checks/ directory. There is also a data/ directory, a tutorials/ directory, a doc.go at the root, and a justfile.

The topics on the repository make the scope explicit. They cover alignment, bioengineering, bioinformatics, codon optimizer, computational biology, dna, dna barcode, dna barcoding, fasta, genbank, genetic engineering, golden gate, mash, molecular biology, plasmids, primer design, sequence hashing, synbio and synthetic biology.

So the library spans file formats and operations. The io package handles the formats, since fasta and genbank are topics, and the alphabet package is what a sequence representation is built on. The transform package is where a sequence is changed, which covers the codon optimizer mentioned in the topics. Primers and synthesis cover the design and build side, clone and the golden gate topic cover assembly, seqhash and mash cover sequence hashing, and search covers finding sequences within larger ones.

The design goal in the README is ambitious in a specific way. The stated aim is to be the most complete, open and well used collection of computational synthetic biology tools ever assembled, and the framing is reproducibility. The README contrasts it with copying and pasting strings into random websites to process data, and says the package is well tested and designed for use in industrial, academic and hobbyist settings.

The project is MIT licensed, copyright Timothy Stiles 2026, the default branch is main, and the last push was on 2026-08-01. The last tagged release is v0.31.2 from 2024-10-21.

## The dependency list tells you what the hashing and diffing are built on

The go.mod is short and the module path is github.com/bebop/poly, requiring Go 1.21.

The direct dependencies are ten. Three are for comparison and diffing, github.com/google/go-cmp, pmezard/go-difflib and sergi/go-diff. Two are for hashing, spaolacci/murmur3 and lukechampine.com/blake3, the latter at version 1.1.5. There is lunny/log for logging, mitchellh/go-wordwrap for text wrapping at version 1.0.1, mroth/weightedrand for weighted random selection at version 0.4.1, stretchr/testify for tests, and golang.org/x/exp for experimental standard library pieces.

Two of those choices are worth noting because they are functional decisions rather than conveniences.

The first is the pair of hash functions. Sequence hashing needs a rolling hash, and murmur3 is the classic choice for content-defined chunking, while blake3 is a newer, faster hash with a tree structure. Having both means the library can compute more than one kind of sequence hash, and the mash topic suggests a mash-style digest is among them.

The second is weightedrand in a package called random. A uniform random sequence is easy; a random sequence with a specified GC content or a specified codon distribution is not, and a weighted selection helper is how you get that. That connects directly to the codon optimizer, where the choice of codons is a distribution rather than a coin flip.

The indirect dependencies are few, which is a good sign for a library that people embed in pipelines. There is mattn/go-sqlite3 and klauspost/cpuid as indirect dependencies, and go-spew and yaml.v2 alongside testify.

## The justfile shows the development loop and the release process

The justfile is short and describes the three things a contributor does, plus how a release is made.

```bash
  go test -v -coverprofile=profile.cov ./...
```

That is the coverage recipe, which runs the whole module with verbose output and writes a coverage profile. The lint recipe runs golangci-lint with the repository's own configuration:

```bash
  golangci-lint -c .golangci.yml run
```

And the test recipe is the plain one:

```bash
  go test -v ./...
```

The interesting recipe is cut-release, which is a two argument recipe taking the new version. It runs lint and then test, so a release cannot be cut without both passing. It then rewrites the CHANGELOG.md with a sed expression that inserts a dated version heading and replaces the Unreleased section, appends a release link line pointing at the GitHub releases tag, and then adds, commits and tags the changelog with a Release version message.

So the version number exists in three places, the changelog heading, the release link and the git tag, and the recipe keeps them consistent. It also reads the current branch with a backtick command substitution, so the recipe is written for the branch you are standing on.

The default recipe just lists the available recipes, which is a small nicety that saves you reading the file. The repository also has a .golangci.yml for the linter configuration, a .devcontainer/ directory, a .vscode/ directory, a CODE_OF_CONDUCT.md and a CONTRIBUTING.md, and a CHANGELOG.md that the release recipe maintains.

## Reading, writing and the format surface

The io/ directory is the entry point to the library, and the format list in the topics tells you what it covers: fasta and genbank are both named.

Genbank in particular is worth calling out, because it is a rich format with features, annotations and sequence records, and a library that reads and writes it is doing real parsing work rather than a line split. The plasmid and genetic engineering topics in the list suggest the sequence records can carry the annotations you would need to work with an actual construct.

The alphabet package is the layer underneath. If you have a sequence object, it has to know which symbols are valid, and the alphabet concept is what makes a DNA sequence and a protein sequence different types rather than the same type with different characters. This is the kind of decision that determines whether the library can be used for the protein work implied by the alignment and bioinformatics topics, or only for DNA.

The checks/ directory is the other one worth noticing. A library that offers to engineer organisms is going to be handed sequences that are wrong, and a checks package for validating them, whether a sequence is a valid nucleotide string or a construct passes some rule, is the kind of thing that has to exist somewhere. Putting it in the library means the validation is the same code in everyone’s pipeline.

The transformation and synthesis packages are where the two halves of the workflow meet. Transform is the compute side, changing a sequence according to rules. Synthesis is the manufacturing side, and with the topics naming golden gate and plasmids, the synthesis package is where the design of an assembly and the plan for building it come together.

## Search, hashing, cloning and randomisation

Four packages cover the operations that are harder than they look.

The seqhash package computes digests over sequences, and the mash topic in the repository topics tells you the flavour. A mash-style digest identifies similar sequences rather than only identical ones, which is what you need when you are comparing a set of related constructs or checking a new sequence against a database of known ones. The presence of both murmur3 and blake3 in the dependency list suggests more than one hash is available, which matters because a rolling hash and a tree hash have different properties for content-defined boundaries.

The search package is the other side of that. Finding a subsequence inside a larger sequence, or finding a set of patterns across many sequences, is a different algorithmic problem from hashing, and having it in the same library means you can search a corpus and hash the hits without a second dependency.

The clone/ directory covers cloning, and the golden gate topic points at what kind of cloning. Golden Gate assembly is a restriction enzyme based method, and supporting it in code means the library can represent the parts, the junctions and the assembly plan, not just the final sequence. Combined with the plasmid topic, the clone package appears to be a design representation rather than a sequence string.

The random/ directory is the fourth, and with weightedrand as a dependency it is about generating sequences under constraints. Combined with the codon optimizer in the transform package, the picture is coherent. A codon optimizer picks, for a given amino acid sequence, a set of codons that meet constraints such as avoiding unwanted motifs or matching a host codon usage. Random is how you sample candidates and transform is how you choose between them.

The fold/ directory is the least obvious name in the list, and the README does not describe it.

## Where Poly is the wrong choice

The first wrong case is a project that needs a maintained dependency. The release history has a gap. Versions 0.31.0 and 0.31.1 were both tagged on 2024-01-31, and 0.31.2 on 2024-10-21, and the last push to the repository was on 2026-08-01. The repository publishes no releases beyond those tags, so if your pipeline needs a versioned artefact you are choosing between a tag from late 2024 and an untagged head, and neither option is a clean answer to a dependency audit.

The second is a team that does not work in Go. The whole argument for Poly is that it is written in a language designed to be fast, scalable and easy to develop in and maintain, and that is a Go argument. If your bioinformatics stack is Python, the standard scientific libraries will be a better fit, and the reproducibility argument goes with them.

The third is a project that needs the full synthetic biology stack. Poly is a library of sequence operations. Wet-lab scheduling, liquid handling, plate maps and instrument control are not here, and the tutorials directory and the Learning Synbio project are teaching resources rather than an execution engine.

The fourth is a one-off task. If you need one primer design or one alignment, writing a Go program against this library is more work than the single command line tool that already does it, and the library's own value is in a pipeline where you call the same operations many times.

The alternative worth weighing is a Python stack built on Biopython and its ecosystem, where the same operations are available as mature libraries with more documentation, at the cost of the language. If you are starting a pipeline from scratch and have no Go in your team, that is the cheaper path, and the honest comparison is that you are trading runtime speed for reach.

## Conclusion

Adopt Poly if you are doing synthetic biology work in Go and want sequence handling, primer design and hashing in one library rather than in a pile of scripts, since the package is organised by task with its own packages for each. Keep away if you need an actively released dependency, because the last tagged release is v0.31.2 from 2024-10-21 while the last push was on 2026-08-01, so the version you get is a choice between an old tag and an untagged head. Before you build on it, read the tutorials directory in the repository, and check the go.mod requirement of Go 1.21 along with the pinned dependencies, since the hashing and diffing libraries are fixed at specific versions.

## FAQ

### What is Poly and what can it do?

It is a Go package for engineering organisms, with packages for sequence input and output, transformation, primer design, synthesis, search, sequence hashing, cloning, alphabets, random sequence generation and checks. The repository topics name the formats and techniques it covers, including fasta, genbank, codon optimization, golden gate assembly, plasmids and mash-style hashing.

### How do I install Poly and run its tests?

Install it with go get github.com/bebop/poly@latest. The repository ships a justfile where the test recipe runs go test -v ./..., the coverage recipe writes a profile with go test -v -coverprofile=profile.cov ./..., and lint runs golangci-lint with the repository's own configuration file.

### Which hashing and comparison libraries does Poly use?

The go.mod lists spaolacci/murmur3 and lukechampine.com/blake3 for hashing, and google/go-cmp, pmezard/go-difflib and sergi/go-diff for comparison and diffing. It also pulls in mroth/weightedrand for weighted random selection, which is how the random package generates sequences under constraints.

### What Go version does Poly require and how is a release cut?

The go.mod requires Go 1.21. A release is cut with the justfile cut-release recipe, which runs lint and test first, then rewrites the CHANGELOG.md with a dated heading and a release link, and finally commits and tags the changelog.

## Sources

- [bebop/poly on GitHub](https://github.com/bebop/poly)
- [License: MIT](https://github.com/bebop/poly/blob/main/LICENSE)
- [Project website](https://pkg.go.dev/github.com/bebop/poly)
- [README](https://github.com/bebop/poly/blob/main/README.md)
- [Releases](https://github.com/bebop/poly/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bebop-poly
