mino.mobi / splice / docs

Docs — architecture & approach

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.

① What SpliceCraft is

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

② The core tension

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.

③ Easy 90% vs hard 10%

Python the language is the easy thing to replace. From reading the source, most of SpliceCraft is ordinary application code with nothing language-specific:

The hard 10% is three scientific dependencies — but each is hard for a different reason, which changes the strategy.

④ The three hard dependencies

DependencyWhat it providesWhy it's hardReuse 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

⑤ Using the C libs from Rust — the mechanics

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.

⑥ Where it runs changes everything

"Use the C as-is" is free for one target and progressively harder for the others:

Targetprimer3HMMERWhat 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.

⑦ Why a game fits on top

Can we put a game over the useful tool? Yes — and it fits better than most "gamified tool" ideas, for one structural reason.

The tool is its own scoring oracle

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.

Cloning is already a constraint-satisfaction puzzle

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.

The one real design risk

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

⑧ Spike result: HMMER → WASM is viable

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/):

CheckResult
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 SSE2bit-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.

Deployment

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.

Sources & references

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

Rust biology crates: rust-bio · noodles · gb-io