An interface for running arbitrary CLI applications for biology and chemistry. It focuses on tools with permissive licencing, and ones which are most popular. Available as a rust library, a python library, and a standalone CLI application.
Includes the most popular tools for structure prediction, sequence prediction, and drug design broadly. For example:
- AlphaFold 3
- ProteinMPNN and LigandMPNN
- Boltz-2 / BoltzGen
- RFdiffusion and RFantibody
- Chai-1
- Protenix
- BindCraft
- OpenDDE
- ImmuneBuilder
- ThermoMPNN
Around 35 more are covered; see Tool::ALL and tool_definitions::catalog for the full set, each with its
own summary, license, and official links.
Handles the following tasks:
- Install
- Uninstall
- Run (Including abstractions over what inputs are accepted per tool)
- Check status/health
- View metadata
Note: Many of these tools only work on Linux. If you attempt to install one of these on Windows,
you will get an error explicitly stating this. The list commands also will state which tools
are Linux only, if you are on a different OS.
pip install bio_tools_app --break-system-packages
bio_tools install open_dde
bio_tools run open_dde --version
bio_tools list-quickNote: Does not break system packages; this just downloads a binary and adds it to the path. That override is required only on certain Linux distributions.
pip install bio_tools_app
(See note above about --break-system-packages if you get an error when running this)
This installs the prebuilt bio_tools executable onto your PATH. uv tool install bio_tools_app works too.
Alternatively, download a prebuilt binary from the Releases page, or build it with Cargo:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install bio_toolsAny of these leaves you with bio_tools on your path.
uv add athanor_bio_tools
Or
pip install athanor_bio_tools
The PyPI distribution is named athanor_bio_tools. The module you import is bio_tools.
cargo add bio_tools
Run the program with no parameters to see its functionality:
bio_tools
Usage:
bio_tools [--root <directory>] install <tool>
bio_tools [--root <directory>] uninstall <tool>
bio_tools [--root <directory>] status-quick <tool>
bio_tools [--root <directory>] status or status-full <tool>
bio_tools [--root <directory>] run <tool> [-- <tool arguments...>]
bio_tools [--root <directory>] list-quick
bio_tools [--root <directory>] list or list-full
bio_tools metadata <tool>Examples:
bio_tools install boltzbio_tools uninstall proteinmpnnbio_tools list-quick
This library provides an interface for input and output. This abstracts over the differences between tools, so applications can add many of them without repeating code. This library was built as the backbone of the Athanor Bio Tools web UI, and the external tool integrations in Molchanica. These use the Python and Rust libraries respectively. Bio Tools is designed to reduce repetition between these projects.
The CLI application is intended for cases where you're not writing software, but want to easily install these tools directly, without handling the system dependencies and python environments for each tool.
Handles installing applications. Details depend on the tool; some work by placing application executables in the appropriate places. Since many of these use Python, it uses uv to set up isolated environments.
The Rust installer replaces application-owned shell and PowerShell orchestration. The caller owns
the outer directory; bio_tools owns the stable per-tool layout, downloads, environments, GPU
selection, and verification.
InstallLayout::process_executables standardizes both consumers on assets under
process_executables/ and environments under process_executables/python_envs/.
InstallLayout::split remains available for custom roots. A progress callback can be attached with
Installer::with_reporter for a GUI or structured setup log.
Rust:
use bio_tools::{install::Installer, tool_definitions::Tool};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut installer = Installer::for_process_executables("process_executables")?;
installer.install(Tool::OpenDde)?;
// Independent recipes continue after an upstream failure.
let report = installer.install_many([Tool::Boltz2, Tool::ProteinMpnn]);
for failure in &report.failed {
eprintln!("{}: {}", failure.tool.name(), failure.error);
}
// Status: `status_quick` inspects markers, executables, and required assets
// without launching the tool; `status_full` also runs its help/version probe.
let status = installer.status_quick(Tool::OpenDde);
println!("{:?}: {}", status.result, status.detail);
let report = installer.uninstall(Tool::OpenDde)?;
println!("Removed {} paths", report.removed.len());
Ok(())
}Python (equivalent):
from pathlib import Path
import bio_tools
root = Path("process_executables")
installer = bio_tools.Installer(root)
installer.install(bio_tools.Tool("opendde"))
# Independent recipes continue after an upstream failure.
for slug in ("boltz2", "proteinmpnn"):
try:
installer.install(bio_tools.Tool(slug))
except RuntimeError as error:
print(f"{slug}: {error}")
status = installer.status_quick(bio_tools.Tool("opendde"))
print(status.result, status.detail)
report = installer.uninstall(bio_tools.Tool("opendde"))
print(f"Removed {len(report.removed)} paths")run::CommandSpec describes a shell-free invocation independently of any one
tool. CommandRunner builds a std::process::Command, overlays environment
variables, writes optional stdin (or closes it when absent), drains bounded
stdout and stderr concurrently, enforces a timeout, and either returns or
rejects non-zero exits according to ExitPolicy.
Rust:
use std::time::Duration;
use bio_tools::run::{CommandSpec, RunLogSpec, run};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let command = CommandSpec::new("opendde")
.args(["predict", "input.yaml"])
.current_dir("work")
.timeout(Duration::from_secs(600))
.run_log(RunLogSpec::new("process_executables/run_logs", "opendde").artifact("."));
let output = run(&command)?;
println!("{}", output.stdout_lossy());
Ok(())
}Python (equivalent):
from pathlib import Path
import bio_tools
result = bio_tools.Command(
["opendde", "predict", "input.yaml"],
cwd=Path("work"),
timeout=600,
run_log_dir=Path("process_executables/run_logs"),
run_name="opendde",
).run()
print(result.stdout)
print(result.run_log_dir)Installer::tool_command (Python: Installer.run) is the variant to reach for when the tool lives in a
managed environment rather than on PATH; it resolves the installed console entry point for you.
When a run log is configured, each invocation gets a unique directory below the given root and run
name. run.log combines the exact argument vector, optional stdin, result, and complete
stdout/stderr. The same streams are also available as stdout.txt and stderr.txt; inputs/
contains the pre-run artifact snapshot and outputs/ contains only files created or changed by the
command. The in-memory output limit does not truncate these on-disk stream files.
The bio_tools executable wraps the same installer, status, and command-runner APIs for shell use:
bio_tools install opendde
bio_tools status-quick opendde
bio_tools status opendde
bio_tools metadata opendde
bio_tools run opendde -- --help
bio_tools list-quick
bio_tools list
bio_tools dir
bio_tools uninstall openddedir prints the directory tools are installed to, along with the sub-directories holding tool assets
and Python environments, and which of the settings below chose it. It creates nothing.
status-quick inspects installation markers, executables, and required assets without launching the
tool. status or status-full (They do the same) also runs the tool's help/version probe and imports Torch or JAX where applicable
to report its compute device. The corresponding list commands are list-quick and list or list-full.
run resolves an installed
console entry point inside that managed environment, so it does not require the tool on PATH. Tools
that only expose a Python module or checkout script still need a tool-specific library invocation.
The CLI installs into one per-user directory, so the same tools are found no matter which directory
bio_tools is launched from. Environments and model weights can reach tens of gigabytes, so it is
the platform's per-user data directory rather than a configuration or roaming one:
| OS | Directory | Typical path |
|---|---|---|
| Linux | $XDG_DATA_HOME/bio_tools, or ~/.local/share/bio_tools when XDG_DATA_HOME is unset |
/home/alice/.local/share/bio_tools |
| macOS | ~/Library/Application Support/bio_tools |
/Users/alice/Library/Application Support/bio_tools |
| Windows | %LOCALAPPDATA%\bio_tools, i.e. %USERPROFILE%\AppData\Local\bio_tools |
C:\Users\alice\AppData\Local\bio_tools |
Inside it, tools/ holds source checkouts, binary distributions, and model data, and each tool's
isolated Python environment is a sibling directory named <tool>-venv.
Two settings override that default, highest precedence first:
--root <directory>, for one invocation$BIO_TOOLS_ROOT, for every invocation in that environment
Run bio_tools dir to print the directory in effect and which of the three chose it. The library
API takes its root as an argument and has no default; bio_tools::install::default_root() returns
the same canonical directory for callers that want it.
- Building a GUI (Web or native application) to these tools
- Setting up an API to programmatically interface.
The python/ package builds an ABI3 wheel with PyO3 and maturin, published to PyPI as
athanor_bio_tools. It exposes the same process metadata, command runner, installer, and status
probes; see the examples above, and the Rust docs for details on the
underlying types.
The python_cli/ package is unrelated to those bindings: it wraps the compiled bio_tools
executable in a wheel, published to PyPI as bio_tools_app, so the CLI can be installed with
pip.
Run this from the project root. You only need the first step if you don't have the Rust toolchain installed. (And that specific command is for Linux; MacOS and Windows have similarly straightforward ways to install it)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo b --releaseThe binary will be placed in bio_tools/target/release