uv pip install hivemind_bus_clientVerify with hivemind-client --help.
websocket-client, ovos-bus-client, poorman-handshake (RSA + PBKDF2), pycryptodomex (AES-GCM, ChaCha20; imports are Cryptodome.*), pybase64, bitstring (binary protocol), z85base91 (payload encodings).
Cryptographic handshake negotiates a session key via RSA or shared password (PBKDF2). All subsequent traffic is encrypted using AES-GCM or ChaCha20-Poly1305. The cipher is negotiated during handshake based on CPU capabilities (optimal_ciphers — encryption.py). Supports wss:// for additional transport-layer security.
- Client sends
HANDSHAKEwith supported ciphers/encodings and either a password envelope or RSA pubkey. - Server responds with its own envelope.
HiveMindSlaveProtocol.receive_handshake(protocol.py) derives the shared secret and setscrypto_key.- Client sends
HELLOwith its public key, session, and site_id. Source:handle_handshake—protocol.py
Either via CLI (hivemind-client set-identity --key X --password Y --siteid Z) or programmatically via NodeIdentity (identity.py). Credentials are stored in ~/.config/hivemind/_identity.json.
HiveMessageBusClient.__init__ raises RuntimeError if access_key, password, or default_master are missing. Source: HiveMessageBusClient.__init__ in client.py
The fundamental message unit. Wraps a payload with routing metadata (msg_type, route, source_peer, target_peers, target_site_id). Source: HiveMessage — message.py
HiveMessageType enum (message.py): HANDSHAKE, BUS, SHARED_BUS, INTERCOM, BROADCAST, PROPAGATE, ESCALATE, HELLO, QUERY, CASCADE, PING, RENDEZVOUS, BINARY.
BUS: Standard message sent to the hub for processing (like a regular OVOS bus message).BROADCAST: Hub forwards to all connected satellites (admin-only, downstream only).PROPAGATE: Forwards to all peers — both upstream and downstream.ESCALATE: Forwards upstream only through the authority chain.
HiveMessage.payload (message.py) reconstructs the appropriate type: Message for BUS/SHARED_BUS, nested HiveMessage for BROADCAST/PROPAGATE/CASCADE/ESCALATE, raw dict otherwise.
Yes. HiveMessage.__init__ normalizes nested HiveMessage payloads to dict via as_dict. The payload property reconstructs them on access.
handle_cascade (protocol.py) buffers responses in a CascadeAggregator (protocol.py). After cascade_timeout seconds (default 5.0) or when expected_responses are collected, the cascade_select_callback picks the best response. Default callback is random.choice over the collected responses. Set HiveMindSlaveProtocol.cascade_select_callback for custom disambiguation.
If HiveMindSlaveProtocol.hive_mapper is set (a HiveMapper instance from prior PING discovery), the aggregator uses len(hive_mapper.nodes) as the expected count and resolves early when all nodes respond. Without a mapper, it falls back to the timeout.
PROPAGATE(BUS) and INTERCOM messages are only injected into the internal bus if the source peer's public key is in NodeIdentity.trusted_keys. Messages from untrusted peers are dropped with a warning. INTERCOM messages explicitly targeted at this node (via target_public_key) are always accepted. Source: _is_source_trusted — protocol.py, handle_propagate — protocol.py, handle_intercom — protocol.py.
identity.add_trusted_key("hub-alias", "<peer_public_key>")
identity.save()Source: NodeIdentity.add_trusted_key — identity.py.
After PING discovery, call mapper.mark_trusted_nodes(identity.trusted_keys) to set NodeInfo.trusted for each discovered node whose public key matches. Source: HiveMapper.mark_trusted_nodes — hive_map.py.
get_bitstring / decode_bitstring (serialization.py) encode messages as compact bitstrings: 1-bit padding marker, 1-bit versioned flag, optional 8-bit protocol version, 5-bit message type, 1-bit compression flag, 8-bit metadata length, metadata bytes, then payload. Binary messages get an additional 4-bit HiveMindBinaryPayloadType field.
Binary (bitstring) is used when both client and server support binarize (negotiated during handshake). JSON is the fallback. HELLO and HANDSHAKE messages are always sent as JSON. Source: HiveMessageBusClient.emit in client.py
Subclass BinaryDataCallbacks (client.py) and pass an instance to the client constructor. Override handle_receive_tts for TTS audio and handle_receive_file for file transfers.
AES-GCM (128/192/256-bit keys) and ChaCha20-Poly1305 (256-bit keys). optimal_ciphers() (encryption.py) prefers AES-GCM on CPUs with AES-NI, ChaCha20 otherwise.
SupportedEncodings (encryption.py): JSON-B64, JSON-URLSAFE-B64, JSON-B32, JSON-HEX, JSON-Z85B, JSON-Z85P, JSON-B91.
Encrypts plaintext, splits into nonce/ciphertext/tag, encodes each with the chosen encoding, and returns a JSON object with those three fields. Decoding reverses the process. Source: encrypt_as_json and decrypt_from_json in encryption.py
It extends MessageBusClient with: HiveMind handshake, automatic encryption/decryption, binary protocol support, routing context injection, and HiveMessage event system. It's designed as a near drop-in replacement. Source: HiveMessageBusClient in client.py
on(event_name, func) (client.py) auto-detects whether event_name is a HiveMessageType (registers on the HiveMind emitter) or an OVOS message type (registers on the internal bus). This makes migration from ovos-bus-client seamless.
For BUS messages, emit() (client.py) auto-injects source, platform, destination, and session into message.context if not already present.
emit_intercom uses hybrid encryption. It generates a random AES-256 key, encrypts the payload with AES-GCM, RSA-encrypts only the AES key with the target node's public key, and signs the ciphertext with the sender's private key. Only the target node can decrypt it. The envelope is wrapped in a HiveMessageType.INTERCOM message, which has no binary wire code and therefore always travels as a text frame.
set-identity, terminal, send-mycroft, escalate, propagate, test-identity, forget-server, reset-pgp, ping. Run hivemind-client --help for the full list. Source: hmclient_cmds in scripts.py