>_ZWIRE-HOST
One pipe. One binary. The whole machine — reachable from anywhere. zwire-host is a single self-contained Rust binary (~500 KB, no Python, no psutil) that exposes the local machine to any app over one JSON message protocol. It began as the Chrome native-messaging host for zwire's HUD; it is now a universal local endpoint reachable from a browser extension and from tmux, emacs, desktop apps, plugins, shell scripts, and any language — because it also runs as a local-socket daemon speaking newline-delimited JSON, the one protocol every tool already has.
Two transports, one dispatcher
Both transports feed the same capability router (src/session.rs), so every command works over either one. A request may carry an id that is echoed on the matching reply, so a client can multiplex many in-flight requests, streams and terminals over one connection.
| Native messaging (default) | Chrome / browser extensions — little-endian u32 length + JSON body on stdin/stdout |
Local-socket daemon (serve) | tmux, emacs, desktop apps, plugins, any language — newline-delimited JSON, one object per line, over a Unix domain socket (macOS/Linux) or a named pipe (Windows) |
The socket is created 0600 under a 0700 dir — owner-only, since it exposes exec/fs/pty. Inbound TCP peers are gated by a shared --token; local Unix-socket clients are trusted.
Capabilities
| System stats | sysinfo_once / sysinfo_start / sysinfo_stop — stream cpu · mem · swap · disk · net rate · load · uptime · battery · temp · host · LAN/WAN ip |
| Filesystem | fs_read / fs_write / fs_append / fs_list / fs_walk (recursive crawl) / fs_stat / fs_mkdir / fs_rm; leading ~ accepted |
| Watch & tail | fs_watch streams create/modify/remove events; fs_tail streams appended lines (tail -f, survives rotation); watch_stop / watch_list |
| Exec & OS | exec (run to completion, base64 stdout/stderr), open, clipboard_get / clipboard_set, notify |
| Background jobs | job_start spawns a job that survives the connection and fires a desktop notification on completion; job_list / job_result / job_poll |
| Process tools | ps (by memory), kill (signal), which (resolve on $PATH) |
| Pub/sub bus | sub / unsub / pub — the host as a coordination hub; it publishes on scheme/ui for live theme sync without polling |
| Host-to-host peering | peers / peer_connect / remote — a mesh of TCP-peered daemons that federates the bus across machines and runs a request on another host |
| PTY terminals | pty_spawn / pty_write / pty_resize / pty_kill, multiplexed by id |
| Key/value store | kv_set / kv_get / kv_merge / kv_del / kv_keys — a per-app JSON store under ~/.<app>/kv/ |
| Discovery | hello (feature-test caps), hostinfo (os, arch, kernel, hostname, user, cpus, mem, LAN ip) |
CLI
zwire-host call is the portable path — one request, one reply, from any tool that can write a line. Add --stream to keep printing frames from a streaming command.
zwire-host serve & # run the socket daemon
zwire-host call '{"cmd":"hostinfo"}' # one request, one reply
zwire-host call '{"cmd":"fs_walk","path":"~/src","ext":"rs"}'
echo '{"cmd":"exec","program":"git","args":["status"]}' | zwire-host call
zwire-host call --stream '{"cmd":"sysinfo_start"}' # keep printing frames
Or talk to the endpoint directly with no client library — e.g. printf '{"cmd":"sysinfo_once"}\n' | nc -U ~/.zwire/host.sock on macOS/Linux.
Library use (embed as a dependency)
The crate is a library too (zwire_host), so sibling hosts (e.g. zpwrchrome-host) can pull it in to crawl and exec without re-implementing anything. Embedders that only need the light capabilities can set default-features = false to drop the heavy sysinfo and portable-pty dependencies.
use zwire_host::api;
// crawl the filesystem
for e in api::walk("~/src", Some("rs")) {
println!("{}", e.path.display());
}
// run a command, get bytes back
let out = api::exec("git", ["status", "--porcelain"]).unwrap();
println!("exit {:?}: {}", out.code, out.stdout_str());
Or drive the whole dispatcher yourself over any transport with zwire_host::{Peer, Session}, or delegate main to zwire_host::run(std::env::args().skip(1).collect()).
Chrome install
Point a native-messaging host manifest's path at the binary and list the allowed extension origins, then drop it in the browser's NativeMessagingHosts/ directory:
{ "name": "com.zwire.hud", "type": "stdio",
"path": "/abs/path/to/zwire-host",
"allowed_origins": ["chrome-extension://<id>/"] }
zwire's scripts/localinstall.sh builds this binary and wires the manifest automatically when packaging the .app.
Build & test
cargo build --release # -> target/release/zwire-host (~500 KB) cargo test # exercises the protocol over both transports cargo fmt --all --check cargo clippy --all-targets -- -D warnings
sysinfo and portable-pty abstract the OS, so the same source builds for macOS · Linux · Windows; CI runs the four polish gates on all three. Battery reporting is macOS-only (via pmset) until a native reader lands for other platforms.
Source layout
src/session.rs | the capability router shared by every transport — per-connection state (PTYs, sysinfo stream, bus/peer links) and the command dispatch |
src/transport.rs | the three ways to reach the dispatcher: stdio native messaging, the serve daemon, and the call client |
src/proto.rs / src/peer.rs | framing + reply plumbing; the peer/mesh link and TCP federation |
src/fsops.rs / src/watch.rs | filesystem read/write/crawl; streaming watch + tail observers |
src/exec.rs / src/jobs.rs / src/procs.rs | run-to-completion exec; background jobs; ps/kill/which |
src/sysmon.rs / src/osops.rs | the sysinfo stream monitor; open/clipboard/notify/hostinfo |
src/pty.rs / src/bus.rs / src/store.rs | multiplexed PTY sessions; pub/sub bus; per-app kv store |
src/api.rs | the light library surface (walk, exec, …) for embedders with default-features = false |
The zwire stack
zwire-host is the local endpoint behind the zwire HUD and its siblings. Browse the rest via the MenkeTechnologiesMeta umbrella repo:
- zwire — the browser HUD this host was born to feed
- zpwrchrome — sibling Chrome extension;
zpwrchrome-hostembeds this crate - strykelang — the scripting language across the stack