Skip to content

Ayushmania2002/boltzyml

Repository files navigation

BoltzYML pipeline overview

BoltzYML

Two browser tools for Boltz-2 structure & binding prediction —
v1 generates local-CLI YAML for ternary complexes · v2.0 builds & submits hosted-API jobs for any complex.

PyPI version Python versions PyPI downloads License GitHub stars Web app Zenodo DOI

🧪  BoltzYML v1 🚀  BoltzYML v2.0
Open v1 web app → Open v2.0 web app →
Ternary Protein 1 + Ligand + Protein 2 preprocessing. Drop two CIFs → emits a ready-to-run Boltz CLI YAML (version: 1) with pocket constraints and an affinity block, for local boltz predict. Also shipped as a PyPI CLI.

v1 details below
Any binary / ternary / N-body complex (protein · ligand · DNA · RNA). Builds the hosted Boltz-2 API payload, auto-cleans template CIFs in the browser, and submits with your own API key — then polls jobs and downloads results.

v2.0 details below

v1 details  ·  v1 CLI  ·  How v1 works  ·  v2.0 details  ·  How to use v2.0  ·  Get an API key


BoltzYML v1 — ternary CLI-YAML generator

index.html + PyPI CLI — the original tool. Live at https://ayushmania2002.github.io/boltzyml/. Generates the open-source Boltz CLI YAML (version: 1) for running boltz predict on your own machine.

When to use BoltzYML v1

Use this tool only if you want to study how the interaction between two proteins changes in the presence of a ligand.

That is the one scenario it is built for: a small molecule sits in a pocket of Protein 1, and you want Boltz-2 to predict how Protein 1 and Protein 2 dock together while that ligand is bound (or absent, as a control). Typical use cases:

  • ABA signaling: PYR/PYL/RCAR receptor + ABA + PP2C phosphatase
  • Allosteric drug screens where a ligand is expected to enable or block partner binding
  • Any ternary system where the ligand sits on Protein 1 and you care about the Protein 1 ↔ Protein 2 interface

If your problem is just protein–protein docking, just protein–ligand docking, or anything that is not a ternary Protein 1 + Ligand + Protein 2 complex, BoltzYML will not help — write the YAML directly or use the Boltz-2 examples.


What it does

You hand BoltzYML two CIF files:

Input Contents Role
protein1_ligand.cif Protein 1 bound to the ligand (docked structure, e.g. AlphaFill, Glide, AutoDock) Source of Protein 1 sequence + ligand identity + pocket residues
protein1_protein2.cif Protein 1 together with Protein 2 (e.g. AlphaFold3 prediction) Source of Protein 2 sequence

BoltzYML then runs entirely in your browser (or via the CLI) and produces a single Boltz-2 v1 YAML with:

  1. Protein 1 sequence on chain A
  2. The ligand on chain B (with its PDB CCD code)
  3. Protein 2 sequence on chain C
  4. A pocket constraint listing the Protein 1 CA atoms within a cutoff of the ligand
  5. An affinity property block targeting the ligand

That YAML is then fed straight into the Boltz-2 CLI.


Two ways to run it

1. Web app (recommended)

Open https://ayushmania2002.github.io/boltzyml/, drop in the two CIFs, click Generate YAML, download the file.

Everything happens in your browser — no uploads, no server, no telemetry. Works on any modern browser, no installation required.

2. Command-line interface

Install from PyPI:

pip install boltzyml

Then run:

boltzyml \
    --ligand   PYL2_ABA.cif \
    --complex  PYL2_PP2C30.cif \
    --output   PYL2_ABA_PP2C30.yaml

Pure Python 3.10+, zero runtime dependencies (no gemmi, no numpy, no pyyaml required).

You can also clone the repo and run it as a module without installing:

git clone https://github.com/Ayushmania2002/boltzyml.git
cd boltzyml
pip install -e .
boltzyml --ligand A.cif --complex B.cif -o out.yaml

CLI options

Flag Description Default
--ligand CIF with Protein 1 + Ligand required
--complex CIF with Protein 1 + Protein 2 required
-o, --output Output YAML path {ligand-stem}__{complex-stem}.yaml
--job-name Job name used for the default output filename derived
--cutoff CA-to-ligand distance cutoff in Å 6.0
--ccd Override the ligand CCD code (used verbatim in the YAML's ccd: field) auto-detect
--no-affinity Skip the affinity prediction block off
--no-pocket Skip the pocket constraints block off
--no-force Emit force: false on the pocket block off
-v, --verbose Print detected chains, ligand, and contacts off

How it works

  1. Parse both CIFs. The parser handles two layouts seen in the wild: single-line atom records (AlphaFold3 style, 18 fields per line) and two-line records (some AlphaFill outputs, 21 fields split 17 + 4).
  2. Identify the ligand. The first non-water HETATM whose comp ID is not a standard amino acid is taken as the ligand. If the CIF labels it generically (LIG, UNL, UNK), the tool warns and asks for a CCD override.
  3. Assign chains. Protein 1 = the longest protein chain in the ligand CIF. The corresponding chain in the complex CIF is matched by 5-mer overlap similarity; the remaining chain is Protein 2.
  4. Compute pocket contacts. CA atoms of Protein 1 within --cutoff Å of any ligand atom are emitted as [A, residue_number] entries, using the CIF's auth_seq_id so the numbers match Boltz-2's own residue numbering.
  5. Emit YAML. A deterministic Boltz-2 v1 YAML is written out, in the field order Boltz-2 expects.

Why CA-only at 6 Å? CA-to-ligand at 6 Å approximates all-atom contacts at ~4 Å, which is the right scale for the soft pocket constraint Boltz-2 applies as an inference-time potential.


Example output

version: 1
sequences:
  - protein:
      id: A
      sequence: MEAHVERALREGLTEEERAALEPAVMAHHTFPPSTTTATTAAATCTSLVTQRVAAPVRAVWPIVRSFGNPQRYKHFVRTCALAAGDGASVGSVREVTVVSGLPASTSTERLEMLDDDRHIISFRVVGGQHRLRNYRSVTSVTEFQPPAAGPAPAPPYCVVVESYVVDVPDGNTAEDTRMFTDTVVKLNLQKLAAVAEDSSSASRRRD
  - ligand:
      id: B
      ccd: A8S
  - protein:
      id: C
      sequence: MAEICCEVVAGSSSEGKGPECDTGSRAARRRR...
constraints:
  - pocket:
      binder: B
      contacts:
        - [A, 76]    # PHE76
        - [A, 98]    # VAL98
        - [A, 103]   # PRO103
        - [A, 104]   # ALA104
        - [A, 107]   # SER107
        - [A, 130]   # HIS130
        - [A, 131]   # ARG131
        - [A, 132]   # LEU132
        - [A, 181]   # THR181
        - [A, 184]   # VAL184
        - [A, 185]   # VAL185
      max_distance: 6.0
      force: true
properties:
  - affinity:
      binder: B

Running Boltz-2 on the output

pip install boltz

boltz predict job.yaml \
    --use_msa_server \
    --use_potentials \
    --diffusion_samples 3 \
    --recycling_steps  3 \
    --step_scale       1.638

Key result files:

File Contents
*_model_0.pdb Predicted ternary structure
confidence_*.json iptm, ptm, ligand_iptm
affinity_*.json affinity_pred_value in kcal/mol
pae_*.npz Predicted aligned error matrix

Sanity checks:

  • iptm > 0.6 — confident protein–protein interface
  • ligand_iptm > 0.5 — confident ligand placement
  • A low off-diagonal block between chain A and chain C in the PAE map = confident interaction

BoltzYML v2.0 — hosted-API builder & submitter

v2.html — the second, broader tool. Live at https://ayushmania2002.github.io/boltzyml/v2.html.

BoltzYML v2.0 workflow: define a complex and clean templates in the browser, submit through a stateless Cloudflare Worker proxy to the Boltz-2 API, then download the complete results.

Where v1 emits local-CLI YAML, v2.0 targets the hosted Boltz-2 API. It builds the API payload (entities / templates / binding / model_options), repairs your template CIFs in the browser, and submits jobs with your own API key. It is not limited to ternary complexes — define any binary, ternary, or N-body mix of proteins, ligands (CCD or SMILES), DNA, and RNA.

Stage Capability
1 · Build Arbitrary entity sets (protein / ligand / DNA / RNA), per-chain IDs, binder selection, live residue/base counts, and sampling control matched to the API (num_samples 1–10, recycling_steps 1–10, sampling_steps ≥50, step_scale 1.3–2.0). Ligands by CCD code, SMILES, or a structure file (.sdf/.mol/.mol2) converted to SMILES in-browser via self-hosted RDKit. Per-protein MSA: automatic, single-sequence, or upload your own .a3m/.csv.
1 · Clean templates Drop a raw RCSB/ChimeraX .cif/.pdb. BoltzYML rewrites _struct_asym to remove phantom chains, strips waters/ligands, repairs modified residues (e.g. OCY → CYS), deletes _pdbx_poly_seq_scheme / _struct_conn records, and rebuilds polymer metadata for raw PDB files — the exact fixes that otherwise make the Boltz template parser fail. Then map each template chain to a prediction chain (one template per chain; duplicates are dropped).
2 · Submit Name the job (optional), estimate the exact cost via Boltz's estimate-cost endpoint before you commit, then paste your own Boltz API key and submit. No setup, no install. Your key lives only in your browser tab and is forwarded to Boltz through BoltzYML's open-source proxy, which stores nothing.
3 · Results Jobs poll themselves with a spinner (no over-clicking) and show the run time (from Boltz timestamps). View the structure in-browser (3Dmol viewer): colored by pLDDT confidence or chain, hover for residue name/number/chain, and drag-select residues from the sequence strip to highlight the interface in 3D. Read ipTM / pTM / pLDDT, and download a results .zip (every sample CIF + metrics.json + a branded README.txt) plus the best structure by ipTM.

Using BoltzYML v2.0 — just bring your Boltz API key

No installation, no proxy setup. The whole workflow is drop files → paste key → submit → download:

  1. Get a Boltz API key (instructions below).
  2. Open the app: https://ayushmania2002.github.io/boltzyml/v2.html
  3. Define your complex — add entities (protein sequence, ligand, DNA, RNA), give each a single-letter chain ID, and mark a ligand as binder if you want affinity/pose scoring. Sequence fields show a live amino-acid / base count.
    • Ligands can be entered three ways: a CCD code (e.g. A8S), a SMILES string, or an uploaded structure file (.sdf / .mol / .mol2). File ligands are converted to SMILES in your browser (self-hosted RDKit, ~7 MB loaded on first use); the result is shown in an editable field so you can verify it before submitting.
    • MSA (per protein): the default is server-generated (recommended). You can also choose single-sequence, or upload your own MSA (.a3m or .csv) on any protein entity. The MSA field is protein-only, so in mixed complexes (protein + DNA/RNA/ligand) it simply applies to the protein chains.
  4. (Optional) Drop a template — a .cif/.pdb from RCSB, AlphaFold, ChimeraX, etc. BoltzYML auto-cleans it in your browser (and converts legacy PDB to mmCIF, emitting the polymer metadata Boltz needs); then map each template chain to a prediction chain. Boltz allows one template per chain, so duplicate mappings are dropped automatically.
  5. Set sampling options (or keep the defaults) and click Rebuild to preview the exact payload.
  6. (Optional) Name the job and click Estimate cost to get Boltz's exact USD estimate before committing.
  7. Paste your Boltz API key and click Submit prediction. Running jobs poll themselves with a spinner, so you do not need to keep clicking.
  8. Under Jobs & results, once succeeded, click View 3D to see the predicted structure right in the page (colored by pLDDT confidence or by chain), or Download results — a .zip of every sample structure + metrics.json + README.txt, plus the best structure by ipTM. Files use your job name when set.

Getting a Boltz API key & cost

The hosted Boltz-2 API is a paid service, run by Boltz — separate from BoltzYML.

  1. Go to the Boltz API docs, create an account, and generate an API key.
  2. Boltz includes $5 of free credit every month; paid top-ups / subscriptions are available — check the current rates on the Boltz site/docs .
  3. Paste the key into BoltzYML v2.0. It stays in your browser tab only (optionally remembered for the session) and is never sent anywhere except through the proxy to Boltz.

Cost. Pricing is per sample (Boltz bills num_samples units), starting around $0.025–$0.05 per sample and scaling with complex size, so a typical job is on the order of a few cents up to ~$0.50. Rather than guess, BoltzYML has an Estimate cost button that calls Boltz's official estimate-cost endpoint and shows the exact USD figure for your payload before you submit. Confirm current rates on the Boltz site, since pricing can change.

Endpoints, pricing, and rate limits may change. Always check the official docs for current details.

How your inputs are processed — and what is (not) stored

All parsing and cleaning happens in your browser. Your raw files are never uploaded for processing.

  1. In your browser (client-side JavaScript):
    • Sequences and ligand codes you type stay local.
    • When you drop a template CIF/PDB, BoltzYML parses it locally and: detects which chains actually have coordinates, rewrites _struct_asym to drop phantom chains, strips waters/ligands (HETATM), maps modified residues (e.g. OCY → CYS) to standard parents, and removes _pdbx_poly_seq_scheme / _struct_conn metadata that would otherwise crash the Boltz parser.
    • It assembles the Boltz API payload (entities / templates / binding / model_options).
  2. At submission, your browser sends the already-cleaned payload plus your API key to the proxy — a small, stateless, open-source Cloudflare Worker (worker/worker.js). The proxy:
    • uploads each cleaned template to transient storage so Boltz can fetch it by URL,
    • forwards the payload to api.boltz.bio with your key in a request header,
    • relays status polls and proxies result downloads (Boltz's result files are otherwise CORS-blocked for browsers).

Data handling / privacy:

  • Your API key is forwarded to Boltz once per request and is never logged or stored by the proxy.
  • Your sequences / payload pass through the proxy to Boltz and are not stored by the proxy.
  • Cleaned template files are the only thing held, and only transiently — in a per-template Durable Object that auto-expires after 2 hours (Boltz needs a fetchable URL for templates).
  • The proxy is stateless and open-source, so you can read exactly what it does.

Why a proxy at all?

api.boltz.bio sends no CORS headers, so a static page (GitHub Pages) can't call it directly, and result files are likewise CORS-blocked. v2.0 therefore routes through a tiny stateless Cloudflare Worker. The public app uses a hosted proxy maintained by the author — you don't deploy anything.

Prefer to run your own proxy? (e.g. for a lab, or to use your own free-tier quota.) Deploy the included Worker in a few minutes:

cd worker
npx wrangler login
npx wrangler deploy   # Durable Object migrations create the stores automatically

Then fork the app and change the hardcoded PROXY_URL constant in v2.html to your Worker's URL. (By design there is no runtime ?proxy= override — see Security below.) See worker/README.md. Templates are held in a strongly-consistent Durable Object (readable globally the instant they are written, so Boltz's fetch never races a slow KV propagation) and auto-expire after 2 hours. No payment method is required.

Security & anti-tampering

Because users supply their own (paid) Boltz API key, BoltzYML v2.0 has undergone an extensive security review focused on protecting that credential. The safeguards in place:

  • Key transmission. The API key is sent only over TLS/HTTPS, and only in a request header (X-Boltz-Key) — never in a URL, query string, or request body. This keeps it out of browser history, server access logs, Referer headers, and analytics. It is transmitted to exactly one origin: the hardcoded proxy.
  • Key storage. The key lives in volatile sessionStorage only when the user opts in, and is cleared when the tab closes. It is never written to localStorage and never leaves the browser except as above.
  • No runtime proxy override (anti-phishing). The proxy endpoint is a hardcoded constant with no ?proxy= / query-string override. This deliberately removes a link-based key-exfiltration / open-redirect vector (a crafted ?proxy=https://attacker.example link cannot retarget the key).
  • XSS / injection hardening. All dynamic or untrusted content — Boltz API responses, error messages, and any text derived from uploaded files — is rendered via textContent / DOM text nodes, not innerHTML, neutralizing reflected, stored, and DOM-based cross-site scripting.
  • Stateless, least-privilege proxy. The Cloudflare Worker holds no credentials of its own, forwards each key to api.boltz.bio exactly once, and never logs or persists it.
  • SSRF / open-proxy guard. The result-download endpoint (/fetch) is restricted by a host allow-list (*.amazonaws.com, *.boltz.bio), so it cannot be abused to fetch arbitrary URLs.
  • Client-side processing. Template parsing and CIF cleaning run entirely in the browser; raw user files are never uploaded for processing.
  • Transient, isolated storage. Cleaned templates live in per-template Durable Objects that auto-expire after 2 hours; the visit counter uses a separate Durable Object. No persistent user data is retained.
  • Transport security. Served exclusively over HTTPS (GitHub Pages + Cloudflare TLS).

The proxy is open-source (worker/worker.js) so every one of these claims is independently verifiable. Found a vulnerability? Please open a security issue.

Boltz API — SDKs for advanced / programmatic use

You don't need these to use BoltzYML (the web tool handles everything), but the Boltz API ships official client libraries if you want to script submissions directly:

Language Install Docs
TypeScript 0.43.0 npm install boltz-api docs
Python 0.33.0 pip install boltz-api docs
Go v0.23.0 go get -u 'github.com/boltz-bio/boltz-api-go@v0.0.1' docs
CLI v0.28.0 irm https://install.boltz.bio/boltz-api/install.ps1 | iex docs

Project layout

boltzyml/
├── index.html              # v1 web app — ternary CLI-YAML generator (GitHub Pages)
├── v2.html                 # v2.0 web app — hosted-API builder, template cleaner, submitter
├── vendor/rdkit/           # Self-hosted RDKit WASM — ligand file → SMILES, loaded on demand
├── vendor/3dmol/           # Self-hosted 3Dmol.js — in-browser structure viewer, loaded on demand
├── worker/                 # Stateless Cloudflare Worker proxy for v2.0 submission
│   ├── worker.js           #   key passthrough + template hosting (Durable Object) + result fetch
│   ├── wrangler.toml       #   deploy config (Durable Object bindings)
│   └── README.md           #   one-time deploy instructions
├── boltzyml_v2_workflow.svg/.png  # v2.0 workflow figure (site + README)
├── logo.png                # Wordmark — favicon + header logo
├── banner.png              # Pipeline schematic — used in this README
│
├── pyproject.toml          # PyPI packaging metadata (hatchling)
├── LICENSE                 # MIT
│
├── src/boltzyml/
│   ├── __init__.py         # Public API re-exports
│   ├── cli.py              # CLI entry point (boltzyml command)
│   ├── parser.py           # CIF parser (1-line and 2-line layouts)
│   ├── contacts.py         # CA-to-ligand pocket contact computation
│   ├── utils.py            # Chain assignment via k-mer similarity
│   └── yaml_writer.py      # Boltz-2 v1 YAML emitter
│
└── tests/
    ├── test_parser.py      # Synthetic CIFs for both layouts
    ├── test_contacts.py    # Cutoff filtering, missing ligand, chain remap
    └── test_cli.py         # End-to-end CLI smoke test

Tests

pip install -e ".[dev]"
pytest

Or run each file directly without pytest:

python tests/test_parser.py
python tests/test_contacts.py
python tests/test_cli.py

Each script exits non-zero on failure and prints all tests passed otherwise.


Gotchas

  • LIG / UNL / UNK ligands. Docking tools often name the ligand generically. The real PDB CCD code (e.g. A8S for abscisic acid, ATP, HEM) belongs in the ccd: field — use the CCD override in the web app or --ccd on the CLI. Verify codes at https://www.rcsb.org/ligand/.
  • Residue numbering. Boltz-2 uses auth_seq_id from your CIF. If your CIF starts at residue 14 (truncated structure), the pocket numbers will start at 14 too — that is correct.
  • Apo vs holo Protein 1. For the ligand CIF, use the holo (ligand-bound) structure, not the apo AlphaFold prediction, so the pocket is in the right conformation.
  • Tamarind Bio users. The same YAML works on https://app.tamarind.bio/boltz. Do not include a templates: block when submitting there — use Tamarind's UI fields for template CIFs instead.

Citation

If you use BoltzYML in published or shared work, please cite both of the following.

1. BoltzYML (this tool):

Mallick, A. BoltzYML: input preparation and hosted-API submission tools for Boltz-2 structure and binding prediction. Zenodo (2026). Concept DOI (always latest): https://doi.org/10.5281/zenodo.20397272 · v2.0: https://doi.org/10.5281/zenodo.20440141

The concept DOI above always resolves to the newest release; cite a version DOI if you need to pin the exact version you used (v1: 10.5281/zenodo.20399843 · v2.0: 10.5281/zenodo.20440141).

BibTeX:

@software{boltzyml_2026,
  author    = {Mallick, Ayushman},
  title     = {{BoltzYML}: input preparation and hosted-API submission
               tools for Boltz-2 structure and binding prediction},
  year      = {2026},
  publisher = {Zenodo},
  version   = {2.0.0},
  doi       = {10.5281/zenodo.20397272},
  url       = {https://doi.org/10.5281/zenodo.20397272}
}

2. Boltz-2 (the upstream model BoltzYML produces input for):

Wohlwend, J. et al. Boltz-2: Towards Accurate and Efficient Binding Affinity Prediction. 2024. https://github.com/jwohlwend/boltz

If you use the ligand-file → SMILES conversion, also acknowledge RDKit (see below).


Acknowledgements

  • RDKit — ligand structure files (.sdf / .mol / .mol2) are converted to SMILES in the browser using RDKit (RDKit.js / @rdkit/rdkit), redistributed in vendor/rdkit/ under the BSD 3-Clause License (Copyright © Valence Discovery Inc., Greg Landrum, Paolo Tosco, and other RDKit contributors). See vendor/rdkit/LICENSE. RDKit: Open-source cheminformatics. https://www.rdkit.org.
  • 3Dmol.js — the in-browser structure viewer (pLDDT / chain coloring) uses 3Dmol.js, redistributed in vendor/3dmol/ under the BSD 3-Clause License. See vendor/3dmol/LICENSE. Rego & Koes, 3Dmol.js: molecular visualization with WebGL, Bioinformatics (2015).
  • Boltz — for the Boltz-2 models and the hosted API.

License

MIT. Copyright © 2026 Ayushman Mallick. Bundled third-party components retain their own licenses (e.g. RDKit, BSD 3-Clause, in vendor/rdkit/LICENSE).

About

Preprocessing file generator (v1) and hosted Boltz-2 API builder/submitter (v2.0): binary, ternary, or N-body protein-ligand-DNA-RNA binding prediction.

Topics

Resources

License

Stars

12 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors