# Cargo Features in OpenHuman's Build Process: A Complete Guide to Conditional Compilation

> Learn how OpenHuman utilizes Cargo features for conditional compilation, managing contributor defaults, product releases, and runtime domain gates in its build process.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: how-to-guide
- Published: 2026-08-31

---

**OpenHuman uses Cargo feature flags to control three orthogonal aspects of the build: contributor defaults, product releases, and runtime domain gates.**

The `tinyhumansai/openhuman` repository implements a sophisticated two-level feature model that separates compile-time code inclusion from runtime activation. This architecture enables fast local development while producing minimal, secure production binaries.

## The Three Aspect Model of Cargo Features

OpenHuman's build system controls three distinct concerns through feature flags:

| Aspect | Purpose | Definition Location |
|--------|---------|---------------------|
| **Contributor feature set** | Developer tools, linters, and test helpers enabled by default | [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml) → `[features] default = [...]` |
| **Product feature set** | Crates shipped in the released desktop application | [`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt) |
| **Domain-level runtime gates** | Runtime switches for domain families (documents, web3, voice, channels, flows) | [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs) |

## Compile-Time Features vs. Runtime Domain Gates

The codebase deliberately decouples two systems for maximum flexibility.

**Compile-time features** in `[features]` are the **only** mechanism to remove code from the final binary. Use these to exclude heavy dependencies like `libgit2-sys`, `ring`, `bzip2-sys`, and `zstd-sys` from production builds.

**Runtime domain gates** via `DomainSet` keep code compiled but skip registration of controllers, stores, and agent tools. This reduces startup time and memory without recompilation.

A developer can compile all domains for full debug support while CI produces aggressively trimmed production binaries.

## Feature Forwarding to the Tauri Shell

OpenHuman ships a Tauri desktop shell in `app/src-tauri/`. The shell depends on the core crate **without** default features:

```toml

# app/src-tauri/Cargo.toml

openhuman_core = { path = "../../", default-features = false, features = ["product"] }

```

The repository enforces consistency through `scripts/ci/check-feature-forwarding.mjs`. This script validates three invariants:

1. Every feature in [`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt) exists in core's `[features]`
2. Every default core feature is explicitly forwarded to the Tauri shell, unless listed in `INTENTIONALLY_NOT_FORWARDED` (currently only `tui`)
3. Forwarding sets are equal—no stray features enter the shell

### Adding a New Feature

Follow this checklist when introducing features:

1. Add the flag to root [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml)
2. Append to [`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt) if shipping in product
3. Update `scripts/ci/check-feature-forwarding.mjs` or add to `INTENTIONALLY_NOT_FORWARDED`

## Key Feature Flags in OpenHuman

Several features demonstrate the system's design:

- **`voice`** — Adds STT/TTS and podcast generation; pulls in heavy `cpal` audio stack; product-enabled but contributor-disabled
- **`web3`** — Enables wallet and EVM/Bitcoin/Solana support; brings in `ethers-core` and `coins-bip39`
- **`documents`** — Activates document generation tools; implicitly enables `modules` for PDF/DOCX codecs
- **`tui`** — Terminal UI via `ratatui` and `crossterm`; **intentionally not forwarded** to desktop shell

All flags reside in root [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml) with descriptive comments.

## Build Scripts and Feature Usage

| Script | Feature Handling |
|--------|----------------|
| [`scripts/ci/full.yml`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/full.yml) | `cargo build --features "$(bash scripts/ci/product-features.sh)"` |
| [`scripts/ci/lite.yml`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/lite.yml) | Fast `cargo check` with default (developer) features |
| [`scripts/kernel-floor.sh`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/kernel-floor.sh) | Computes minimal dependencies for kernel-only builds |
| `scripts/check-feature-forwarding.mjs` | Validates core-to-shell feature forwarding |

### Computing the Kernel Floor

The [`scripts/kernel-floor.sh`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/kernel-floor.sh) script determines the minimal dependency graph when compiling with `--no-default-features --features flows`. This prevents unintentional kernel footprint growth.

## Building with Cargo Features

### Full Product Binary

```bash

# Match CI production builds exactly

cargo build --release --features "$(bash scripts/ci/product-features.sh)"

```

### Minimal Kernel-Only Binary

```bash

# Smallest possible runtime: flows domain only

cargo build --release --no-default-features --features "flows"

```

### Runtime Domain Disabling

```rust
use openhuman_core::core::runtime::builder::{DomainSet, ServiceSet};
use openhuman_core::core::CoreBuilder;

// Exclude voice domain at runtime without recompilation
let core = CoreBuilder::new()
    .domains(DomainSet::full().without_voice())
    .services(ServiceSet::desktop())
    .build()
    .await?;

```

Method names follow the `without_<domain>()` pattern—see [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs) for available helpers.

## Adding a New Feature: Complete Example

Implementing an `augmented_reality` feature:

**1. Declare in root [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml):**

```toml
[features]

# existing flags…

augmented_reality = []

```

**2. Add to product set if shipping:**

```bash
echo "augmented_reality" >> scripts/ci/product-features.txt

```

**3. The forwarding script reads [`product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/product-features.txt) automatically—no edit needed unless intentional exclusion.**

**4. Use conditional compilation:**

```rust
#[cfg(feature = "augmented_reality")]
mod ar {
    // AR-specific domain implementation
}

```

## Why This Architecture Matters

- **Binary size:** Dropping native crates reduces `openhuman-core` from ~300 MiB to ~67 MiB
- **Security surface:** Native code features (`voice`, `web3`) only present when explicitly enabled
- **CI speed:** Lite lane compiles default features only; full lane validates production readiness
- **Future-proofing:** New domains gate behind compile-time flags first, then graduate to product set

## Key Source Files

| File | Purpose |
|------|---------|
| [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml) (root) | Single source of truth for compile-time features |
| [`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt) | Shipped product feature list |
| `scripts/ci/check-feature-forwarding.mjs` | Core-to-shell consistency enforcement |
| [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs) | Runtime `DomainSet` implementation |
| `scripts/kernel-floor.limits` | Kernel dependency budget |
| [`app/src-tauri/Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/Cargo.toml) | Tauri shell feature forwarding example |

## Summary

- OpenHuman's Cargo features operate at **three levels**: contributor defaults, product releases, and runtime domain gates
- **Compile-time features** control binary content; **runtime gates** control activation without recompilation
- The **Tauri shell** disables default features and receives exact product set via forwarding scripts
- **CI scripts** maintain consistency: [`product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/product-features.txt) defines releases, `check-feature-forwarding.mjs` prevents drift
- **Kernel floor tracking** ensures minimal dependencies for core-only builds

## Frequently Asked Questions

### What is the difference between default features and product features in OpenHuman?

Default features enable the full contributor experience with linters, test helpers, and optional native crates. Product features are the minimal set defined in [`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt) that ship in released desktop applications. The Tauri shell explicitly disables defaults with `default-features = false` and enables only the product set.

### How do I exclude a domain without recompiling OpenHuman?

Use `DomainSet::full().without_<domain>()` when building the core. The code remains compiled—the domain simply isn't registered at startup. This pattern is implemented in [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs) with methods like `without_voice()` for each available domain.

### Why is the `tui` feature intentionally not forwarded to the desktop shell?

The `tui` feature pulls in `ratatui` and `crossterm` for terminal interfaces, which are unnecessary for the Tauri-based desktop application. Listing it in `INTENTIONALLY_NOT_FORWARDED` within `scripts/ci/check-feature-forwarding.mjs` prevents these crates from entering the desktop binary while keeping them available for headless or contributor builds.