How OpenHuman's CLI Architecture Handles ServiceSet Resolution and HostKind Detection
OpenHuman's CLI orchestrates runtime initialization through two distinct phases: HostKind detection in src/core/host/mod.rs to determine the execution environment (Desktop, TUI, or Standalone), followed by ServiceSet resolution in src/core/runtime/builder.rs to configure which background services (RPC, WebSocket, cron) should start based on detected host type and explicit CLI flags.
The command-line interface in the tinyhumansai/openhuman repository serves as the central orchestration point for the entire system. Located in src/core/cli.rs, the CLI initialization flow determines the runtime personality of the application through environment detection and service configuration. Understanding this CLI architecture is essential for deploying OpenHuman across diverse environments from desktop applications to headless servers.
HostKind Detection Strategy
The first initialization phase identifies the execution context through the HostKind enum.
Environment Detection Logic
In src/core/host/mod.rs, the HostKind::detect() method performs runtime inspection to classify the environment. This function evaluates three specific conditions to determine the appropriate host variant.
Runtime Inspection Criteria
The detection algorithm checks for:
- Tauri Runtime: Presence of
window.__TAURI__indicates a desktop webview context - TTY Availability: Standard input being a TTY signals terminal UI (TUI) mode
- Standalone Fallback: Absence of the above conditions defaults to
HostKind::Standalonefor headless server operation
The resulting HostKind variant (Desktop, Tui, or Standalone) propagates through the builder pattern to influence logging initialization and UI defaults.
ServiceSet Resolution Mechanism
After host detection, the CLI determines which background services to instantiate through the ServiceSet type.
CLI Flag Parsing
Located in src/core/runtime/builder.rs, the ServiceSet struct consumes arguments parsed by clap. Explicit flags such as --rpc, --socket, --cron, and --channels map directly to service activation via ServiceSet::from_cli(&args).
Context-Aware Defaults
When no explicit service flags are provided, the system applies sensible defaults based on the previously detected HostKind:
- Desktop: Enables
rpc_http,socketio, cron scheduler, and channel integrations - Standalone: Restricts to
rpc_httponly for API server operation - TUI: Initializes with no background services, as the terminal interface drives core functionality directly
Core Builder Integration
The resolved components assemble through CoreBuilder in a sequential flow:
// src/core/cli.rs ─ entry point
fn main() -> Result<()> {
// 1️⃣ Parse command‑line arguments (clap)
let args = Cli::parse();
// 2️⃣ Detect the host environment
let host = HostKind::detect(); // src/core/host/mod.rs
// 3️⃣ Resolve which services to run
let services = ServiceSet::from_cli(&args); // src/core/runtime/builder.rs
// 4️⃣ Assemble the core runtime
let core = CoreBuilder::new(host)
.services(services)
.domains(DomainSet::full()) // all domain families
.build()
.await?;
// 5️⃣ Dispatch the chosen sub‑command (run, serve, etc.)
core.run_subcommand(args.subcommand)
}
This architecture ensures that HostKind detection tailors logging (file-only for TUI versus Tauri window initialization) while ServiceSet resolution centralizes service lifecycle decisions.
Deployment Patterns and Examples
The unified binary adapts to multiple deployment scenarios without recompilation.
Desktop Application (Default Services)
$ openhuman # no flags → Desktop host detection
# HostKind = Desktop, ServiceSet = { rpc_http, socketio, cron, channels, ... }
Headless API Server
$ openhuman serve --rpc # explicit service selection
# HostKind = Standalone, ServiceSet = { rpc_http }
Terminal UI Mode
$ openhuman tui # forces HostKind::Tui
# HostKind = Tui, ServiceSet = {} (no background services; UI drives the core)
Custom Service Composition
$ openhuman serve --rpc --cron --no-channels
# HostKind = Standalone
# ServiceSet = { rpc_http, cron } // channels deliberately omitted
Summary
- HostKind detection in
src/core/host/mod.rsdetermines the runtime environment by inspecting Tauri presence and TTY status, returningDesktop,Tui, orStandalonevariants. - ServiceSet resolution in
src/core/runtime/builder.rstranslates CLI flags (--rpc,--socket, etc.) into service configurations, applying HostKind-specific defaults when flags are omitted. - The
CoreBuilderpattern insrc/core/cli.rschains these components withDomainSet::full()to produce a tailored runtime. - This architecture enables a single binary to function as a desktop app, headless server, or TUI without recompilation.
Frequently Asked Questions
How does OpenHuman detect whether to run in desktop or server mode?
The system calls HostKind::detect() from src/core/host/mod.rs, which checks for the Tauri runtime environment and TTY availability. If it detects window.__TAURI__, it selects HostKind::Desktop; if standard input is a TTY, it selects HostKind::Tui; otherwise it falls back to HostKind::Standalone for server operation.
What happens if I don't specify any service flags when starting OpenHuman?
When no explicit flags like --rpc or --socket are provided, ServiceSet::from_cli() applies default service groups based on the detected HostKind. Desktop hosts automatically enable HTTP RPC, WebSocket, cron, and channels, while Standalone hosts enable only HTTP RPC, and TUI mode starts no background services.
Can I mix explicit service flags with default HostKind behavior?
Yes. The CLI architecture allows you to override specific services while maintaining the HostKind context. For example, running openhuman serve --rpc --cron --no-channels forces a Standalone host while explicitly enabling only RPC and cron services, excluding channels regardless of default settings.
Where is the entry point for the CLI logic?
The main entry point resides in src/core/cli.rs, which coordinates the initialization sequence: parsing arguments with clap, detecting the host environment, resolving the service set, building the core runtime via CoreBuilder, and dispatching subcommands.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →