How splice brings a real cloning workbench to the open web, and why a game fits on top of it. For what's built and what's next, see the roadmap.
SpliceCraft (by Binomica Labs, MIT-licensed) is "your whole cloning workflow, in the terminal" — a molecular-biology workbench built as a Textual TUI in 100% Python on top of BioPython. It does plasmid maps, restriction analysis, primer design, assembly planning (Golden Gate / MoClo / Gibson), local BLAST + HMM search, Sanger verification, in-silico PCR, gel simulation, and a lab notebook.
Crucially for a web port, it already ships a headless mode: a ~130-endpoint localhost JSON HTTP API (splicecraft --agent, bearer-token, 127.0.0.1-only, "single-tenant by design") plus a stdlib-only CLI sidecar. So there is a clean machine surface to build a frontend against — it just isn't multi-tenant or networked today.
Sources: repo · agent-api.md · pyproject.toml
minomobi ships on Cloudflare Pages + Workers — JS/WASM, no persistent Python compute. SpliceCraft is a stateful, single-tenant, native-dependency Python desktop app. There is no drop-in. Worse, the most valuable features lean on compiled C libraries that Pyodide cannot load (Pyodide has no wheels for pyhmmer or primer3-py), so "Python in the browser" loses exactly the hard parts.
The insight that unlocks everything: two of the three hard dependencies are already C. A Rust port can reuse them — bind them natively, or compile them to WASM via Emscripten — instead of reimplementing the science. That makes Rust→WASM a strictly better web target than Python→Pyodide.
Python the language is the easy thing to replace. From reading the source, most of SpliceCraft is ordinary application code with nothing language-specific:
--agent HTTP/JSON server, the string-level biology (IUPAC regex, reverse-complement, circular slicing, wrap-aware feature lengths).The hard 10% is three scientific dependencies — but each is hard for a different reason, which changes the strategy.
| Dependency | What it provides | Why it's hard | Reuse path |
|---|---|---|---|
| BioPython | GenBank/FASTA/GFF3/AB1 parsers, translation across NCBI codon tables, Bio.Restriction over the REBASE enzyme DB (~700 enzymes), Bio.Align | Breadth + curated data, and it's pure Python — no C core to lean on | Re-author in Rust using rust-bio / noodles / gb-io; port the REBASE + codon-table data. Tedious, tractable. (The deterministic subset of this is what's live in the lab today.) |
| primer3 via primer3-py |
Nearest-neighbor (SantaLucia) Tm, salt/Mg/dNTP correction, hairpin/dimer ΔG, primer picking with weighted penalties | A tuned thermodynamics model. Trivial to port (pure double math, params compiled in) — but primer3 is GPL-2.0, which collides with MIT. | Tm: clean-room. The SantaLucia formula + ΔH/ΔS tables are published science, not code — so Tm is reimplemented in Rust (MIT), matching primer3's oligotm to <0.01 °C and live in the lab. A real (GPL) primer3 module is reserved only for thal-grade hairpin/dimer ΔG. |
| HMMER3 via pyhmmer |
Profile-HMM search: Plan7, Viterbi/Forward-Backward, SIMD MSV/SSV filters, Gumbel E-value statistics | ~100k LOC of 20-years-tuned C + the Easel support lib. No production-grade Rust pHMM exists. | It's C → bind/compile, never rewrite. pyhmmer is itself Cython over this same C. (Proven portable — see the spike.) |
And the real moat, independent of language: SpliceCraft's 4,000+ tests asserting biological accuracy. Any reimplementation has to reproduce identical outputs across circular wrap-around features, frame handling, star activity, overhang/ligation rules, gel curves. That accumulated correctness is the expensive thing to match.
Sources: BioPython · REBASE · primer3 · HMMER · pyhmmer · Easel
Rust isn't allergic to C. Reusing libprimer3 and libhmmer "as-is" is a solved problem; the only question is the build target. Both libraries expose a real C API (SpliceCraft links them via primer3-py/pyhmmer rather than shelling out to binaries), so there's an API to bind, not a CLI to fork.
// build.rs — compile the vendored C and link it
fn main() {
cc::Build::new() // the `cc` crate drives the C compiler
.files(glob_primer3_sources())
.include("vendor/primer3/src")
.compile("primer3"); // -> libprimer3.a, linked into the Rust binary
}
// bindgen turns primer3.h into `extern "C"` Rust declarations,
// which we wrap in a safe module. Then:
let tm = unsafe { ffi::oligotm(seq.as_ptr(), /* salt, conc, … */) };
Toolchain pieces: bindgen (header → bindings), the cc crate (compile the C in build.rs), and the Rustonomicon FFI chapter for the unsafe boundary. For HMMER you'd instead drive its autotools/CMake build from build.rs and link libhmmer + Easel.
"Use the C as-is" is free for one target and progressively harder for the others:
| Target | primer3 | HMMER | What it takes |
|---|---|---|---|
| Native Rust server (off-Cloudflare container) |
trivial | standard | Normal FFI: bindgen + cc/build.rs + safe wrapper. Run like the --agent API. A weekend of plumbing per lib. |
| Browser WASM (static site on Pages) |
routine | spiked ✓ | Compile the C to WASM via Emscripten, preload DB/param files into MEMFS, recompile SIMD paths to WASM SIMD, and gate threads behind SharedArrayBuffer + COOP/COEP headers. (The SIMD part — the scary one — is proven.) |
| Cloudflare Worker WASM (server-side at the edge) |
great | marginal | Compile C→WASM in a Worker, expose JSON. primer3 fits easily; HMMER risks the CPU-time / ~128MB ceiling and has no threads — push it to a container or Durable Object. |
Two browser-WASM caveats worth flagging: COOP/COEP is the same cross-origin-isolation requirement labglass already lives with on this infra, so it's a known quantity on Pages; and nothing can shell out to a subprocess in WASM — fine here, because the lib-linking path is what we'd use.
Can we put a game over the useful tool? Yes — and it fits better than most "gamified tool" ideas, for one structural reason.
Most science/edutainment games have to hand-author both the levels and the answer-checking. A cloning engine hands you an objective correctness scorer for free: it can deterministically judge any player move — is this a valid assembly? does this primer pair amplify? is the frame intact? are there internal cutters? The thing that normally kills these projects is solved before we start, which means levels can be procedurally generated and solutions auto-graded. That's exactly how the live game works: your attempt wins iff the engine's recombinant equals the target plasmid. Precedent: Foldit, EteRNA, and Phylo all turned a scored biological problem into play.
The wet-lab loop maps onto game mechanics almost 1:1. Constraints (restriction-site uniqueness, primer Tm windows, overhang compatibility, reading frame, no internal cutters) are the puzzle rules; a valid plasmid is the win. In-silico PCR + gel sim give instant verifiable feedback. And optimization (fewest enzymes, fewest steps, lowest cost) gives Zachtronics-style replay value with leaderboard histograms.
Real cloning carries a lot of bookkeeping. The game layer's entire job is to hide the spreadsheet and surface the decisions — that's Zachtronics' actual craft. If a level exposes a parts-inventory table, it's a tool; if it exposes one interesting choice with consequences, it's a game. That's a hard design constraint from level one.
Sources: Foldit · EteRNA · Phylo · Zachtronics · Fluoddity · rite /redact
Before committing to the plan, the single project-killing unknown was de-risked: does HMMER's SIMD core — hot loops written as hand-tuned SSE intrinsics that don't exist in WebAssembly — survive the trip to WASM? HMMER was cloned and built, its own test suite run, and its hottest kernel ported. Result, with code you can re-run (splice/spike/):
| Check | Result |
|---|---|
| HMMER's own SIMD-vs-reference unit tests (MSV, Viterbi, Fwd/Back, Decoding, OptAcc) | all PASS |
| Real MSV kernel compiled to WASM SIMD128 (via SIMDe) vs native x86 SSE2 | bit-identical |
| WASM-SIMD speed vs native SSE2 (V8 lowers it straight to hardware SSE) | ~6% slower |
So the faithful, in-browser pro-tool tier is real: SIMDe + clang -msimd128 is the porting path, and HMMER's own test suite is the acceptance gate. The only remaining browser cost is profile-DB download size / memory — a data-distribution question, not a feasibility one. Full write-up: spike/VIABILITY.md.
splice ships like /rite: a Cloudflare Worker with an ASSETS binding, custom domain splice.mino.mobi, deployed by .github/workflows/deploy-splice.yml on push. The Rust engine compiles to a ~85 KB wasm32-unknown-unknown module (dependency-free, no wasm-bindgen) committed as a static asset and shared by the lab and the game. /api/health confirms the worker is live.
SpliceCraft: repo · agent API docs · Binomica Labs
Biology libs: BioPython · REBASE · primer3 · HMMER · pyhmmer · Easel · SIMDe
Rust ↔ C / WASM: bindgen · cc crate · Rustonomicon FFI · Emscripten · wasm-bindgen · WASM SIMD · COOP/COEP