Literate Notebooks
BioLang notebooks (.bln files) interleave Markdown prose with executable
BioLang code. They're perfect for documenting analyses, creating reproducible reports,
and sharing results with collaborators.
Quick Start
# Run a notebook in the terminal
bl notebook analysis.bln
# Export to standalone HTML
bl notebook analysis.bln --export html
# Convert from Jupyter
bl notebook experiment.ipynb --from-ipynb > experiment.bln
# Convert to Jupyter
bl notebook experiment.bln --to-ipynb > experiment.ipynb
The .bln Format
A .bln file is plain text. Markdown prose is rendered, and code blocks
are evaluated. Interpreter state carries over between blocks — variables defined
in one block are available in all later blocks.
Fenced Code Blocks
Use standard Markdown fenced code blocks with biolang, bl,
or no language tag:
## Sample Quality Control
Load the FASTQ file and check basic statistics.
```biolang
let reads = read_fastq("sample_R1.fastq.gz")
let stats = read_stats(reads)
print(stats)
```
## Filter Low-Quality Reads
Keep only reads with mean Phred score above 25.
```bl
let filtered = reads |> filter(|r| mean_phred(r.quality) > 25)
print(f"Kept {len(filtered)} of {len(reads)} reads")
```
Dash-Delimited Code Blocks
Alternatively, use --- on its own line to delimit code blocks. This
is the original BioLang notebook format:
## Load Data
Read the FASTA file and compute per-sequence GC content.
---
let seqs = read_fasta("contigs.fa")
let gc_table = seqs |> map(|s| {id: s.id, gc: gc_content(s.seq)}) |> table()
print(gc_table)
---
## Results
The table above shows GC content per contig.
You can mix both styles in the same notebook. Code blocks with other language tags
(e.g. ```python) are treated as prose and displayed but not executed.
Cell Directives
Add special comment annotations at the top of a code block to control how it behaves:
| Directive | Effect |
|---|---|
| # @hide | Execute the code but don't display it in output. Useful for setup code. |
| # @skip | Don't execute this block. Useful for draft or commented-out cells. |
| # @echo | Print the code before executing it. Shows both code and output. |
| # @hide-output | Execute the code (and show it) but suppress any printed output. |
Directives are stripped from the code before execution. You can combine them:
```biolang
# @echo
# @hide-output
let config = {min_quality: 30, threads: 8}
let reference = "GRCh38"
```
HTML Export
Export a notebook to a self-contained HTML file with syntax highlighting and a dark-themed design:
bl notebook analysis.bln --export html > report.html
The HTML output includes inline CSS styling, BioLang syntax highlighting with color-coded keywords, strings, comments, and pipe operators. It's a single file with no external dependencies — perfect for sharing via email or publishing.
Jupyter Interop
Convert between BioLang's .bln format and Jupyter's .ipynb
format for compatibility with the Jupyter ecosystem.
Import from Jupyter
# Convert .ipynb to .bln (prints to stdout)
bl notebook experiment.ipynb --from-ipynb > experiment.bln
Markdown cells become prose sections. Code cells are wrapped in fenced
```biolang blocks. Outputs are discarded (they'll be regenerated when
you run the notebook).
Export to Jupyter
# Convert .bln to .ipynb (prints to stdout)
bl notebook analysis.bln --to-ipynb > analysis.ipynb
Prose sections become Markdown cells. Code blocks become code cells with
"language": "biolang" metadata. The resulting notebook uses
nbformat v4 and can be opened in JupyterLab, VS Code, or any notebook viewer.
Terminal Rendering
When you run bl notebook file.bln in a terminal, prose sections are
rendered with ANSI styling:
- Headings — bold, underlined, with level indicators
- Inline code — cyan highlight
- Bold and italic — ANSI bold/italic
- Blockquotes — indented with
|prefix in dim text - Lists — bullet points with indentation
Code blocks are executed in order. Output is interleaved between prose sections, making it easy to follow an analysis step by step.
Example Notebook
Here's a complete .bln notebook demonstrating the key features:
# GC Content Analysis
This notebook analyzes GC content across a set of contigs
and identifies potential outliers.
## Setup
```biolang
# @hide
let min_gc = 0.3
let max_gc = 0.7
```
## Load Data
Read the FASTA file and compute per-sequence statistics.
```biolang
let seqs = read_fasta("contigs.fa")
print(f"Loaded {len(seqs)} sequences")
```
## Compute GC Content
```biolang
# @echo
let gc_values = seqs |> map(|s| gc_content(s.seq))
let mean_gc = mean(gc_values)
let std_gc = stdev(gc_values)
print(f"Mean GC: {mean_gc:.3f} +/- {std_gc:.4f}")
```
## Identify Outliers
Flag contigs with GC content more than 2 standard deviations
from the mean — these may indicate contamination or
horizontal gene transfer.
```biolang
let outliers = seqs
|> filter(|s| {
let gc = gc_content(s.seq)
abs(gc - mean_gc) > 2.0 * std_gc
})
print(f"Found {len(outliers)} outlier contigs")
outliers |> each(|s| print(f" {s.id}: GC={gc_content(s.seq):.3f}"))
```
## Summary
> The analysis identified potential contaminant contigs based
> on anomalous GC content. Review these sequences before
> downstream assembly or annotation.
Tips
- Use
# @hidefor configuration and imports to keep the narrative clean - Use
# @echofor key analysis steps so readers see both code and results - Use
# @skipto temporarily disable expensive computation during development - Use
# @hide-outputwhen you want to show the code but not its (verbose) output - State carries across cells — define variables once and reuse them throughout
- The HTML export is self-contained: share
report.htmldirectly - Use
--from-ipynbto migrate existing Jupyter notebooks to BioLang