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

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 → [features] default = [...]
Product feature set Crates shipped in the released desktop application scripts/ci/product-features.txt
Domain-level runtime gates Runtime switches for domain families (documents, web3, voice, channels, flows) 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:


# 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 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
  2. Append to 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 with descriptive comments.

Build Scripts and Feature Usage

Script Feature Handling
scripts/ci/full.yml cargo build --features "$(bash scripts/ci/product-features.sh)"
scripts/ci/lite.yml Fast cargo check with default (developer) features
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 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


# Match CI production builds exactly

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

Minimal Kernel-Only Binary


# Smallest possible runtime: flows domain only

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

Runtime Domain Disabling

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 for available helpers.

Adding a New Feature: Complete Example

Implementing an augmented_reality feature:

1. Declare in root Cargo.toml:

[features]

# existing flags…

augmented_reality = []

2. Add to product set if shipping:

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

3. The forwarding script reads product-features.txt automatically—no edit needed unless intentional exclusion.

4. Use conditional compilation:

#[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 (root) Single source of truth for compile-time features
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 Runtime DomainSet implementation
scripts/kernel-floor.limits Kernel dependency budget
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 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →