Tauri Desktop App IPC Bridge to Rust Sidecar: How OpenHuman Connects UI to Core
The OpenHuman desktop application uses a Tauri IPC bridge to relay JSON-RPC calls from the React frontend to a standalone Rust sidecar binary, managing the sidecar lifecycle automatically while keeping business logic isolated from the UI.
OpenHuman’s architecture separates the lightweight desktop interface from heavy computational workloads. The frontend runs inside a Tauri-hosted WebView, while the openhuman-core Rust sidecar handles persistence, QuickJS skill execution, and blockchain operations. This guide examines the IPC bridge implementation that synchronizes these components according to the tinyhumansai/openhuman source code.
The Two-Layer IPC Architecture
The bridge operates through two distinct layers. First, the Tauri IPC command (core_rpc_relay) receives requests from the frontend via the standard Tauri invoke mechanism. Second, an HTTP JSON-RPC client forwards these requests to the sidecar's local API endpoint at http://127.0.0.1:<core_port>/rpc.
This design keeps the WebView sandboxed while allowing access to native system capabilities. All network traffic remains internal to localhost, eliminating CORS concerns and external exposure.
The IPC Relay Command
The entry point resides in app/src-tauri/src/commands/core_relay.rs. When the frontend calls invoke('core_rpc_relay', …), Tauri deserializes the payload into a CoreRpcRequest struct containing three critical fields:
- method: The JSON-RPC method name (e.g.,
agent.run,wallet.prepare_transfer) - params: An optional map of parameters for the method
- serviceManaged: A boolean flag indicating whether Tauri should auto-start the core process
The handler first ensures the sidecar is alive by delegating to the core process manager. Once confirmed, it forwards the request to the HTTP client layer.
Sidecar Lifecycle Management
Before any RPC call reaches the business logic, the system guarantees the sidecar is running. The app/src-tauri/src/core_process.rs module handles this responsibility, implementing logic to either spawn a new openhuman-core binary or reuse an existing child process.
This manager tracks the sidecar's health and port allocation, ensuring the HTTP client always has a valid target endpoint. If serviceManaged is true and the process is not running, the manager initiates startup automatically before the relay proceeds.
HTTP Client Implementation
The actual communication with the sidecar happens in app/src-tauri/src/core_rpc.rs. This client constructs a standards-compliant JSON-RPC envelope:
{
"jsonrpc": "2.0",
"method": "agent.get_profile",
"params": {},
"id": 1
}
The client injects authentication by reading the bearer token from ~/.openhuman-staging/core.token and adding it to the HTTP headers. It then POSTs the envelope to the sidecar's RPC endpoint and returns the response (or error) back through the Tauri command chain to the frontend.
Frontend TypeScript Integration
The React codebase interacts with this bridge through a thin wrapper defined in app/src/utils/coreRpcClient.ts. This utility abstracts the Tauri invoke mechanism:
import { invoke } from '@tauri-apps/api/tauri';
export async function coreRpc<T>(method: string, params?: Record<string, any>) {
const { result } = await invoke('core_rpc_relay', {
request: { method, params },
});
return result as T;
}
// Usage example
const profile = await coreRpc<UserProfile>('agent.get_profile');
All high-level UI operations—wallet transfers, agent execution, memory queries—flow through this helper, maintaining type safety while accessing native Rust capabilities.
Core-Side Request Dispatching
On the receiving end, the sidecar implements a JSON-RPC dispatcher in src/rpc/dispatch.rs and src/rpc/mod.rs. These modules parse incoming requests, route them to the appropriate domain controllers, and serialize responses back to the HTTP client.
This completes the round-trip: TypeScript invokes Tauri → Tauri manages process → HTTP client POSTs → Sidecar dispatches → Response propagates back through the chain.
Summary
- OpenHuman uses a hybrid IPC architecture combining Tauri's native commands with HTTP JSON-RPC for sidecar communication
- The
core_rpc_relaycommand inapp/src-tauri/src/commands/core_relay.rsserves as the sole bridge between frontend and business logic - Automatic lifecycle management via
app/src-tauri/src/core_process.rsensures the sidecar is running before dispatching requests - Authentication uses a bearer token stored in
~/.openhuman-staging/core.token, injected by the HTTP client inapp/src-tauri/src/core_rpc.rs - Frontend code uses the
coreRpchelper inapp/src/utils/coreRpcClient.tsto maintain clean separation between UI and native operations
Frequently Asked Questions
What is the difference between Tauri commands and the sidecar process?
Tauri commands run inside the main Rust process that hosts the WebView, while the sidecar (openhuman-core) is a separate binary launched as a child process. Commands handle window management and OS integration, whereas the sidecar owns business logic like agent execution and wallet management. The IPC bridge connects these two Rust-based components.
How does the application handle sidecar startup and crashes?
The core_process.rs module implements a process manager that monitors the sidecar's lifecycle. When the frontend issues a request with serviceManaged: true, the manager checks if the process is running and spawns it if necessary. The manager tracks the process handle and port binding, automatically restarting if the sidecar becomes unresponsive.
Is the communication between frontend and sidecar secure?
Yes. Although the HTTP traffic flows over localhost, the sidecar requires a bearer token for authentication. The token is stored in the user's home directory at ~/.openhuman-staging/core.token and is injected into every request header by the Tauri-side HTTP client. External processes cannot access this token without system-level privileges.
What happens if the sidecar port is already in use?
The core process manager in app/src-tauri/src/core_process.rs handles port allocation dynamically. If the default port is unavailable, the manager either coordinates with an existing sidecar instance or allocates a new port, ensuring the HTTP client always targets the correct endpoint. The core_rpc_relay command waits for this handshake to complete before forwarding requests.
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 →