<div align="center">
# oxo-call
**Model-intelligent orchestration for CLI bioinformatics**
[](https://github.com/Traitome/oxo-call/actions/workflows/ci.yml)
[](https://crates.io/crates/oxo-call)
[](#license)
[](https://www.rust-lang.org/)
[](#data-storage)
Describe your task in plain language — `oxo-call` fetches the tool's documentation, grounds the request with a built-in skill, and asks your LLM backend to generate the exact flags you need.
</div>
---
## Architecture
```
Natural-language task
│
▼
┌──────────────────────────────────────────────────────────┐
│ oxo-call CLI │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Documentation Layer │ │
│ │ --help output · local index cache · remote URL │ │
│ └───────────────────────┬──────────────────────────┘ │
│ │ combined docs + task │
│ ┌───────────────────────▼──────────────────────────┐ │
│ │ Skill System │ │
│ │ built-in → community registry → user │ │
│ └───────────────────────┬──────────────────────────┘ │
│ │ grounded prompt │
│ ┌───────────────────────▼──────────────────────────┐ │
│ │ LLM Backend │ │
│ │ GitHub Copilot · OpenAI · Anthropic · Ollama │ │
│ └───────────────────────┬──────────────────────────┘ │
│ │ ARGS: ... │
│ ┌───────────────────────▼──────────────────────────┐ │
│ │ Command Execution │ │
│ │ run · dry-run · run --ask │ │
│ └───────────────────────┬──────────────────────────┘ │
│ │ │
│ ┌───────────────────────▼──────────────────────────┐ │
│ │ History & Output │ │
│ │ JSONL log · exit code · timestamp │ │
│ └──────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
---
## Features
- 🧠 **LLM-powered parameter generation** — describe what you want to do, get the right flags
- 📚 **Auto documentation** — `--help` output is cached transparently on first use; enrich with remote URLs, local files, or directories
- 🗂️ **Unified docs management** — `oxo-call docs add/list/show/remove/update` manages the documentation index
- 🔍 **Dry-run mode** — preview commands before executing
- 📜 **Command history** — track every run with exit codes and timestamps
- 🔧 **Flexible LLM backend** — GitHub Copilot (default), OpenAI, Anthropic, Ollama
- 🎯 **Skill system** — built-in expert knowledge for 100+ bioinformatics tools
---
## Quick Start
### 1. Install
```bash
cargo install oxo-call
# or build from source:
cargo install --path .
```
### 2. Obtain a license
A signed license file is required for core commands (free for academic use — see [License](#license)).
```bash
# Place your license.oxo.json at the default path:
# Linux: ~/.config/oxo-call/license.oxo.json
# macOS: ~/Library/Application Support/io.traitome.oxo-call/license.oxo.json
# Or point to it at runtime:
export OXO_CALL_LICENSE=/path/to/license.oxo.json
```
### 3. Configure your LLM token
**GitHub Copilot (default):**
```bash
oxo-call config set llm.api_token <your-github-token>
# Or: export OXO_CALL_LLM_API_TOKEN=... / GITHUB_TOKEN=... / GH_TOKEN=...
```
**OpenAI:**
```bash
oxo-call config set llm.provider openai
oxo-call config set llm.api_token <your-openai-key>
# Or: export OXO_CALL_LLM_PROVIDER=openai OXO_CALL_LLM_API_TOKEN=...
# OPENAI_API_KEY is also accepted as a fallback.
```
**Anthropic:**
```bash
oxo-call config set llm.provider anthropic
oxo-call config set llm.api_token <your-anthropic-key>
# Or: export OXO_CALL_LLM_PROVIDER=anthropic OXO_CALL_LLM_API_TOKEN=...
# ANTHROPIC_API_KEY is also accepted as a fallback.
```
**Ollama (local, no token needed):**
```bash
oxo-call config set llm.provider ollama
oxo-call config set llm.model llama3.2
# Or: export OXO_CALL_LLM_PROVIDER=ollama OXO_CALL_LLM_MODEL=llama3.2
```
### 4. Run with natural language — documentation is fetched automatically
`--help` output is cached on first use, so you can run immediately without a separate indexing step:
```bash
# Preview the command without executing (dry-run)
oxo-call dry-run samtools "sort input.bam by coordinate and output to sorted.bam"
# → samtools sort -o sorted.bam input.bam
# Execute immediately
oxo-call run bwa "align reads.fastq to reference.fa using 8 threads, output SAM"
# Ask for confirmation before executing
oxo-call run --ask bcftools "call variants from my.bam against ref.fa and output to variants.vcf"
```
---
## Commands
<div align="center">
| `run` | `r` | Generate parameters with LLM and execute the tool |
| `dry-run` | `d` | Generate parameters and print the command — no execution |
| `docs` | `doc` | Add, remove, update, list, show, or search cached documentation |
| `config` | `cfg` | Read and write LLM/behavior settings |
| `history` | `hist` | Browse past command runs with exit codes and timestamps |
| `skill` | `sk` | List, show, or manage prompting skill files |
| `workflow` | `wf` | Native workflow engine + Snakemake / Nextflow export |
| `license` | `lic` | Verify your signed license file |
</div>
---
### `run` — Execute a tool with LLM-generated parameters
```
oxo-call run [OPTIONS] <TOOL> <TASK>
oxo-call r [OPTIONS] <TOOL> <TASK> # short alias
Options:
-a, --ask Prompt for confirmation before executing
```
Executes immediately by default. Use `dry-run` to preview first, or `--ask` to confirm before running.
```bash
oxo-call run samtools "view only primary alignments from file.bam and save to primary.bam"
```
---
### `dry-run` — Preview the command without executing
```
oxo-call dry-run <TOOL> <TASK>
oxo-call d <TOOL> <TASK> # short alias
```
```bash
oxo-call dry-run bwa "align paired reads R1.fastq R2.fastq to hg38.fa using 16 threads"
```
---
### `docs` — Manage tool documentation
Documentation is **fetched and cached automatically** on first use — you rarely need to
run `docs add` manually. Use `docs add` when you want to enrich the cache with remote
web documentation, a local manual file, or a directory of docs files.
```
oxo-call docs add <TOOL> [--url <URL>] [--file <PATH>] [--dir <DIR>]
oxo-call docs remove <TOOL>
oxo-call docs update [TOOL] [--url <URL>] # omit TOOL to refresh all
oxo-call docs list
oxo-call docs show <TOOL>
oxo-call docs path <TOOL>
```
```bash
# Index from --help output (usually not needed — done automatically on first run)
oxo-call docs add samtools
# Enrich with a remote man page or docs site
oxo-call docs add bwa --url https://bio-bwa.sourceforge.net/bwa.shtml
# Index a tool that is not installed locally (remote URL only)
oxo-call docs add gatk --url https://gatk.broadinstitute.org/hc/en-us/articles/...
# Add from a local Markdown or text manual
oxo-call docs add mytool --file /path/to/manual.md
# Add all .md/.txt/.rst/.html files from a local docs directory
oxo-call docs add mytool --dir /path/to/docs/
# Refresh all indexed tools
oxo-call docs update
# Inspect what is cached
oxo-call docs show samtools
oxo-call docs list
```
---
### `config` — Manage configuration
```
oxo-call config set <KEY> <VALUE> # Persist a config value
oxo-call config get <KEY> # Show the effective value (env overrides applied)
oxo-call config show # Show all stored and effective values side-by-side
oxo-call config verify # Verify the LLM config with a live API call
oxo-call config path # Print the path to config.toml
```
**Config keys:**
| `llm.provider` | `github-copilot` | `OXO_CALL_LLM_PROVIDER` | LLM provider: `github-copilot`, `openai`, `anthropic`, `ollama` |
| `llm.api_token` | *(unset)* | `OXO_CALL_LLM_API_TOKEN` | API token. Provider-specific env vars are also supported as fallbacks. |
| `llm.api_base` | *(auto)* | `OXO_CALL_LLM_API_BASE` | Override the API base URL |
| `llm.model` | *(auto)* | `OXO_CALL_LLM_MODEL` | Model name (e.g. `gpt-4o`, `claude-3-5-sonnet-20241022`) |
| `llm.max_tokens` | `2048` | `OXO_CALL_LLM_MAX_TOKENS` | Maximum tokens to generate |
| `llm.temperature` | `0.0` | `OXO_CALL_LLM_TEMPERATURE` | Temperature (lower = more deterministic; `0.0` = fully deterministic output) |
| `docs.auto_update` | `true` | `OXO_CALL_DOCS_AUTO_UPDATE` | Auto-refresh docs on first use |
Environment variables override `config.toml` values for every key above.
`oxo-call config verify` makes a real API call to confirm the current provider, token, base URL, and model are working. On failure it prints the upstream error and configuration suggestions.
---
### `history` — Command execution history
```
oxo-call history list [-n <N>] [--tool <TOOL>] # Show recent history
oxo-call history clear [-y] # Clear all history
```
```bash
oxo-call history list # Last 20 commands
oxo-call history list -n 50 # Last 50 commands
oxo-call history list --tool samtools # Filter by tool name
```
---
### `skill` — Manage expert knowledge profiles for tools
Skills are curated TOML files that inject **domain-expert knowledge** into the LLM prompt for a specific bioinformatics tool. They contain key concepts, common pitfalls, and worked command examples. When oxo-call finds a matching skill it includes this knowledge in the prompt, which dramatically improves command accuracy — especially for complex tools and smaller/weaker LLM models.
```
oxo-call skill list # List all available skills (built-in, community, user)
oxo-call skill show <TOOL> # Display the full skill for a tool
oxo-call skill install <TOOL> # Install a skill from the community registry
oxo-call skill install <TOOL> --url <URL> # Install a skill from a custom URL
oxo-call skill remove <TOOL> # Remove a community or user-installed skill
oxo-call skill create <TOOL> # Print a skill TOML template to stdout
oxo-call skill create <TOOL> -o out.toml # Write the template to a file
oxo-call skill path # Show the user skills directory path
```
Examples:
```bash
# See what skills are available
oxo-call skill list
# Inspect the samtools skill (concepts, pitfalls, worked examples)
oxo-call skill show samtools
# Install a community skill for a tool not yet built-in
oxo-call skill install bismark
# Scaffold a new skill file for your own tool
oxo-call skill create mytool -o ~/.config/oxo-call/skills/mytool.toml
```
**Skill load priority** (highest wins):
1. User-defined: `~/.config/oxo-call/skills/<tool>.toml`
2. Community-installed: `~/.local/share/oxo-call/skills/<tool>.toml`
3. Built-in: compiled into the binary (120 tools as of this release)
**Built-in skill coverage** spans all major omics domains:
| QC & preprocessing | samtools, fastp, fastqc, multiqc, trimmomatic, cutadapt, trim_galore, picard, fastq-screen |
| Short-read alignment | bwa, bwa-mem2, bowtie2, hisat2, star, chromap |
| Long-read alignment | minimap2, pbmm2 |
| RNA-seq | salmon, kallisto, rsem, stringtie, featurecounts, trinity, arriba |
| Variant calling (SNV/indel) | gatk, bcftools, freebayes, deepvariant, strelka2, varscan2, longshot |
| Structural variants | manta, delly, sniffles, pbsv, survivor, truvari |
| CNV | cnvkit |
| Variant annotation | snpeff, vep, vcftools, vcfanno |
| Phasing & benchmarking | whatshap, shapeit4, hap_py |
| Epigenomics | macs2, deeptools, bismark, methyldackel, pairtools, homer, modkit |
| Metagenomics | kraken2, bracken, metaphlan, diamond, prokka, bakta, metabat2, checkm2, gtdbtk, humann3, centrifuge |
| Single-cell | cellranger, starsolo, kb, velocyto, cellsnp-lite |
| Long-read (ONT/PacBio) | dorado, nanoplot, nanostat, chopper, porechop, racon, medaka, pbccs, pbfusion, nanocomp |
| De novo assembly | spades, megahit, flye, hifiasm, canu, miniasm, wtdbg2, verkko |
| Assembly QC & polishing | quast, busco, pilon |
| Genome annotation | prodigal, augustus, agat, repeatmasker, annot8r, bakta, liftoff |
| Sequence search & comparison | blast, hmmer, mmseqs2, diamond, mash, sourmash |
| Utilities | seqtk, seqkit, bedtools, bedops, bamtools, samtools, tabix, mosdepth, crossmap, igvtools, sra-tools |
| MSA & phylogenetics | mafft, muscle, iqtree2, fasttree |
| Population genomics | plink2, admixture, angsd |
| Comparative & functional genomics | orthofinder, eggnog-mapper |
---
### `workflow` — Native workflow engine + compatibility export
The `workflow` command ships a **lightweight native Rust workflow engine** that
executes `.oxo.toml` pipeline files directly — no Snakemake, Nextflow, or Conda
required. Snakemake and Nextflow are supported as **compatibility export targets**
for environments that need those formats (e.g., HPC clusters with existing Nextflow
infrastructure).
#### Native engine features
- **DAG-based execution** — steps run in dependency order with full parallelism
across independent tasks via `tokio::task::JoinSet`
- **Wildcard expansion** — `{sample}` automatically expands per sample; `{params.KEY}` for shared parameters
- **Output caching** — steps whose outputs are newer than their inputs are skipped automatically
- **Gather steps** — `gather = true` aggregates across all samples (e.g., MultiQC)
- **Zero external dependencies** — only the bioinformatics tools themselves need to be installed
#### Workflow file format (`.oxo.toml`)
```toml
[workflow]
name = "rnaseq"
description = "Bulk RNA-seq pipeline"
[wildcards]
sample = ["sample1", "sample2", "sample3"] # {sample} expands for each
[params]
threads = "8"
star_index = "/data/star_hg38"
gtf = "/data/gencode.v44.gtf"
[[step]]
name = "fastp"
cmd = "fastp --in1 data/{sample}_R1.fq.gz --in2 data/{sample}_R2.fq.gz ..."
inputs = ["data/{sample}_R1.fq.gz", "data/{sample}_R2.fq.gz"]
outputs = ["trimmed/{sample}_R1.fq.gz", "trimmed/{sample}_R2.fq.gz"]
[[step]]
name = "star"
depends_on = ["fastp"]
cmd = "STAR --genomeDir {params.star_index} ..."
outputs = ["aligned/{sample}/Aligned.sortedByCoord.out.bam"]
[[step]]
name = "multiqc"
gather = true # runs once after all {sample} instances of deps
depends_on = ["fastp", "star"]
cmd = "multiqc qc/ aligned/ -o results/multiqc/"
outputs = ["results/multiqc/multiqc_report.html"]
```
#### Commands
```
oxo-call workflow list # List built-in templates
oxo-call workflow show <NAME> # Print native .oxo.toml template
oxo-call workflow show <NAME> --engine snakemake # Print the Snakemake version
oxo-call workflow show <NAME> --engine nextflow # Print the Nextflow version
oxo-call workflow export <FILE|NAME> --to snakemake # Export as Snakefile
oxo-call workflow export <FILE|NAME> --to nextflow # Export as Nextflow DSL2
oxo-call workflow generate "<TASK>" # LLM-generated native workflow
oxo-call workflow generate "<TASK>" -e snakemake # LLM-generated Snakemake workflow
oxo-call workflow generate "<TASK>" -o wf.toml # Save to file
```
**Built-in templates (native + Snakemake + Nextflow DSL2):**
| `rnaseq` | Bulk RNA-seq | fastp → STAR → featureCounts → MultiQC |
| `wgs` | Whole-genome sequencing | fastp → BWA-MEM2 → GATK BQSR → HaplotypeCaller |
| `atacseq` | ATAC-seq / chromatin accessibility | fastp → Bowtie2 → Picard → MACS3 |
| `metagenomics` | Shotgun metagenomics | fastp → host removal → Kraken2 → Bracken |
Examples:
```bash
# Dry-run the RNA-seq pipeline to preview all steps
oxo-call workflow dry-run rnaseq
# Run the metagenomics workflow from a customised TOML file
cp $(oxo-call workflow show metagenomics > metagenomics.toml && echo metagenomics.toml)
# edit wildcards/params in metagenomics.toml, then:
oxo-call workflow run metagenomics.toml
# Export native workflow to Snakemake for HPC submission
oxo-call workflow export wgs.toml --to snakemake -o Snakefile
# Generate a custom ChIP-seq workflow with LLM (native format by default)
oxo-call workflow generate \
"ChIP-seq for H3K27ac, paired-end, peak calling against input control" \
-o chipseq_h3k27ac.toml
# Preview the generated workflow before running
oxo-call workflow dry-run chipseq_h3k27ac.toml
```
---
### Skills vs Docs — what's the difference?
oxo-call uses **two complementary knowledge sources** when building the LLM prompt:
| **What it is** | Raw `--help` output + optionally fetched web docs for a tool | Curated TOML file with concepts, pitfalls, and worked examples |
| **Created by** | Automatically fetched at runtime from the tool itself or a URL | Written by domain experts; built-ins are compiled into the binary |
| **Content** | Exhaustive flag reference — everything the tool can do | Selective expert commentary on the most important patterns and gotchas |
| **LLM role** | Provides factual grounding so the LLM knows valid flags | Provides reasoning scaffolding so the LLM applies flags correctly |
| **Managed with** | `oxo-call docs` | `oxo-call skill` |
| **Stored at** | `~/.local/share/oxo-call/docs/` | `~/.local/share/oxo-call/skills/` (community) or `~/.config/oxo-call/skills/` (user) |
In practice, `docs` answer *"what flags exist?"* while `skills` answer *"which flags should I use for this task, and what mistakes should I avoid?"* Both are injected into the prompt together for best results.
---
## Environment Variables
| `OXO_CALL_LLM_PROVIDER` | Override `llm.provider` |
| `OXO_CALL_LLM_API_TOKEN` | Override `llm.api_token` |
| `OXO_CALL_LLM_API_BASE` | Override `llm.api_base` |
| `OXO_CALL_LLM_MODEL` | Override `llm.model` |
| `OXO_CALL_LLM_MAX_TOKENS` | Override `llm.max_tokens` |
| `OXO_CALL_LLM_TEMPERATURE` | Override `llm.temperature` |
| `OXO_CALL_DOCS_AUTO_UPDATE` | Override `docs.auto_update` |
| `OXO_CALL_LICENSE` | Path to `license.oxo.json` |
| `GITHUB_TOKEN` | GitHub Copilot API token |
| `GH_TOKEN` | GitHub token (fallback for Copilot) |
| `OPENAI_API_KEY` | OpenAI API token (fallback) |
| `ANTHROPIC_API_KEY` | Anthropic API token (fallback) |
| `OXO_API_TOKEN` | Generic token fallback |
---
## Configuration File
Stored at a platform-appropriate path — run `oxo-call config path` to find yours.
| Linux | `~/.config/oxo-call/config.toml` |
| macOS | `~/Library/Application Support/io.traitome.oxo-call/config.toml` |
| Windows | `%APPDATA%\traitome\oxo-call\config\config.toml` |
---
## Data Storage
Documentation cache and history files:
| Linux | `~/.local/share/oxo-call/` |
| macOS | `~/Library/Application Support/io.traitome.oxo-call/` |
| Windows | `%APPDATA%\traitome\oxo-call\data\` |
---
## Building from Source
```bash
git clone https://github.com/Traitome/oxo-call
cd oxo-call
cargo build --release
# Binary: target/release/oxo-call
```
```bash
# Run tests
cargo test
# Lint
cargo clippy -- -D warnings
cargo fmt -- --check
```
---
## License
**Dual License — Academic Free / Commercial Per-Organization**
<div align="center">
| Academic research, education, personal non-commercial | [LICENSE-ACADEMIC](LICENSE-ACADEMIC) | **Free** — signed license file required |
| Commercial / production (any organization) | [LICENSE-COMMERCIAL](LICENSE-COMMERCIAL) | **USD 100** — per-org, one-time fee |
</div>
### How to obtain a license
All users — academic and commercial — must have a **signed `license.oxo.json`** file to run core commands. Verification is performed **offline** (no network required) using an Ed25519 signature.
#### Academic License (free)
1. Apply at: <https://github.com/Traitome/oxo-call#license>
2. You will receive a `license.oxo.json` file by email.
3. Place it at the default path for your platform (see table below) or set `OXO_CALL_LICENSE`.
#### Commercial License (per-organization, one-time fee)
1. Contact: <w_shixiang@163.com>
2. Pay the **USD 200** authorization fee.
3. You will receive a `license.oxo.json` signed for your organization.
4. One license covers all employees/contractors within your organization.
#### Public academic test license
For quick evaluation and CI-style smoke testing, this repository publishes a public
academic test license at `docs/public-academic-test-license.oxo.json`.
You can copy it into place with:
```bash
# Linux
cp docs/public-academic-test-license.oxo.json ~/.config/oxo-call/license.oxo.json
# macOS
cp docs/public-academic-test-license.oxo.json ~/Library/Application\\ Support/io.traitome.oxo-call/license.oxo.json
```
The published test license content is:
```json
{
"schema": "oxo-call-license-v1",
"license_id": "6548e181-e352-402a-ab72-4da51f49e7b5",
"issued_to_org": "Public Academic Test License (any academic user)",
"license_type": "academic",
"scope": "org",
"perpetual": true,
"issued_at": "2026-03-12",
"signature": "duKJcISYPdyZkw1PbyVil5zTjvLhAYsmbzRpH0n6eRYJET90p1b0rYiHO0cJ7IGR6NLEJWqkY1wBXUkfvUvECw=="
}
```
> **Test use only.** This public academic license is published for evaluation and testing.
> Academic users are still encouraged to apply for a formal academic license.
> Commercial users should contact <w_shixiang@163.com>, pay the **USD 200**
> authorization fee, and obtain a formal commercial license.
#### License file locations
| Linux | `~/.config/oxo-call/license.oxo.json` |
| macOS | `~/Library/Application Support/io.traitome.oxo-call/license.oxo.json` |
| Windows | `%APPDATA%\oxo-call\license.oxo.json` |
```bash
# Option 1 — Copy to the default location (Linux)
cp license.oxo.json ~/.config/oxo-call/license.oxo.json
# Option 2 — CLI flag
oxo-call --license /path/to/license.oxo.json run samtools "..."
# Option 3 — Environment variable
export OXO_CALL_LICENSE=/path/to/license.oxo.json
oxo-call run samtools "..."
# Verify your license
oxo-call license verify
```
> **Skill files** contributed to the community registry are licensed under **CC-BY-4.0** and remain freely usable by everyone.
---
## Developer Notes — Issuing Licenses (Maintainer Only)
The `crates/license-issuer` workspace member provides an offline signing tool.
### Generate a key pair (once per trust root)
```bash
cargo run -p license-issuer --bin license-issuer -- generate-keypair
# Prints: PRIVATE_KEY_SEED=<base64> PUBLIC_KEY=<base64>
# ▸ Store the private key securely (password manager / offline vault).
# ▸ Update EMBEDDED_PUBLIC_KEY_BASE64 in src/license.rs with the public key.
```
### Issue an academic license
```bash
export OXO_LICENSE_PRIVATE_KEY="<your-base64-private-key-seed>"
cargo run -p license-issuer --bin license-issuer -- issue \
--org "Recipient University" \
--email researcher@uni.edu \
--type academic \
--output license.oxo.json
```
### Issue a commercial license
```bash
export OXO_LICENSE_PRIVATE_KEY="<your-base64-private-key-seed>"
cargo run -p license-issuer --bin license-issuer -- issue \
--org "Example Corp" \
--email admin@example.com \
--type commercial \
--output license.oxo.json
```
> **Never commit your private key.** It should only ever exist on an air-gapped machine or in a secure secret store.
For local development and CI, the private key is not needed for `cargo build` / `cargo test`. The repository ships a pre-signed test fixture at `tests/fixtures/test_license.oxo.json` that is verified against the embedded public key in `src/license.rs`. If you rotate the embedded public key, regenerate that fixture with the new private key and commit the updated file.