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::Standalone for 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_http only 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.rs determines the runtime environment by inspecting Tauri presence and TTY status, returning Desktop, Tui, or Standalone variants.
  • ServiceSet resolution in src/core/runtime/builder.rs translates CLI flags (--rpc, --socket, etc.) into service configurations, applying HostKind-specific defaults when flags are omitted.
  • The CoreBuilder pattern in src/core/cli.rs chains these components with DomainSet::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:

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 →