npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

omnius-fabric

v0.12.8

Published

Omnius Fabric: install-to-node encrypted cooperative routing fabric with automatic UPnP, bootstrap discovery, peerbook/DHT building, relay fallback, QR-based connect handshake, rolling-key sessions, and E2E addressable messaging.

Downloads

4,460

Readme

Omnius Fabric

Install-to-node encrypted cooperative routing fabric for Node.js. One npm install turns a machine into a reachable peer: it self-maps a public port, bootstraps off public NATS rendezvous, advertises an NKN overlay fallback, relays for NATed peers, and exchanges end-to-end encrypted messages — addressable by a signed fabric:// ticket.

Architecture

Each node runs a libp2p peer with the services below. The fabric is self-provisioning: any node that becomes publicly reachable (via UPnP/NAT-PMP) automatically serves as a circuit relay for peers that cannot map a port, and public NATS is the default rendezvous that seeds the DHT on a cold start. NKN runs alongside libp2p as an overlay fallback: when connected, the daemon advertises an nkn route hint so peers can still send the same end-to-end encrypted envelope over the public NKN mesh when IP-level reachability is unavailable.

| Service | Purpose | |---|---| | KadDHT | Distributed hash table for peer discovery and route-record storage (/omnius/fabric/kad/1.0.0) | | GossipSub | Pub/sub mesh for route announcements, peer exchange, and metadata | | pubsub peer discovery | Peers announce multiaddrs over a well-known topic; learned peers are dialed and seed the DHT | | Circuit Relay v2 | Relay reservations for NATed peers — client, server, or both (default both) | | DCUtR | Direct Connection Upgrade through Relay — hole-punches NATed peers after relay rendezvous | | Noise | Transport-level encryption (XX handshake, Curve25519, AEAD) | | Yamux | Stream multiplexing over a single connection | | Identify | Protocol and multiaddr exchange between connected peers | | mDNS | Local-network peer discovery (LAN/zeroconf) | | Bootstrap | Static bootstrap peer list for initial DHT seeding (when configured) | | NKN overlay | Name-resolved public p2p mesh used as an additional encrypted delivery fallback; advertised through signed nkn route hints | | Ping | Connectivity health checks |

Libp2p transports: TCP, WebSocket, and Circuit-Relay (client/both modes). NATS acts as an out-of-band rendezvous plus encrypted inbox fallback. NKN is a daemon-level overlay fallback carried in signed address route hints, not a libp2p multiaddr transport.

All protocol identifiers use the /omnius/fabric/... namespace:

| Protocol | String | |---|---| | DHT | /omnius/fabric/kad/1.0.0 | | Direct Message | /omnius/fabric/dm/1.0.0 | | Session | /omnius/fabric/session/1.0.0 | | Route Sync | /omnius/fabric/route-sync/1.0.0 | | Connection Upgrade | /omnius/fabric/upgrade/1.0.0 | | Media Transfer | /omnius/fabric/media/1.0.0 | | Relay Probe | /omnius/fabric/relay-probe/1.0.0 | | Meta (pubsub) | /omnius/fabric/meta/1.0.0 | | Routes (pubsub) | /omnius/fabric/routes/1.0.0 | | PeerX (pubsub) | /omnius/fabric/peerx/1.0.0 | | Relays (pubsub) | /omnius/fabric/relays/1.0.0 |

Discovery cascade

Peers are discovered through every available channel:

  1. Persisted — previously known peers from the local peerbook (peers.json)
  2. Public NATS rendezvous — ON by default. A fresh node learns peers' signed addresses over NATS route gossip, dials them, and — because they speak /omnius/fabric/kad/1.0.0 — seeds its Kademlia routing table. This is the primary cold-start path; generic libp2p/IPFS bootstrap nodes can't seed a custom-protocol DHT.
  3. HTTPS manifests — signed bootstrap manifests from operator-provided remote URLs (opt-in)
  4. libp2p bootstrap@libp2p/bootstrap dials configured multiaddrs
  5. GossipSub peer exchange — route-record gossip + pubsub peer discovery
  6. DHT walking — KadDHT random-walk fills the routing table
  7. mDNS — local-network multicast discovery (zeroconf)
  8. NKN route hints — connected daemons include an nkn address in signed fabric:// tickets so any discovery channel can teach peers the overlay fallback route
  9. Relay reservation discovery — circuit-relay advertisements

Transport selection

When delivering a message the daemon walks a cascade, preferring the most direct path and falling back only as needed:

  1. Direct libp2p — dial the peer's fabric:// route multiaddrs (public IP or UPnP-mapped) over TCP/WebSocket.
  2. Circuit Relay v2 + DCUtR — reach NATed peers through a relay, then hole-punch to a direct path where the NATs allow it.
  3. NATS inbox — brokered fallback. The already-encrypted envelope is published to the recipient's inbox subject; NATS brokers see only opaque ciphertext.
  4. NKN overlay — universal fallback. If the recipient's signed address carries an unexpired nkn hint and this daemon's overlay client is live, the same encrypted envelope is sent to the recipient's NKN address. No public IP, open port, relay reservation, or NATS inbox reachability is required between the two peers.

Connection tiers (trust upgrade)

Relationships between peers are tiered and established by a mutual, double-signed handshake — neither side can fabricate a relationship alone:

| Tier | Name | Unlocks | How established | |---|---|---|---| | T0 | Discovered | route exchange, relay, basic E2E messaging | automatic — the open fabric | | T1 | Trusted | richer messaging, scoped capability delegation | requester asks → target approves → both countersign a TrustGrant | | T2 | Media | file, image, and video sharing in chat (media:share) | requester asks → target approves → both countersign a TrustGrant | | T3 | Administrative | service exposure and scoped administrative access (e.g. shell:exec) | T2-style handshake at the highest bar; target opts in |

Grants carry an Ed25519 signature from both parties (granter + grantee), a capability scopes[] list, and an expiry. Either side can revoke; revocation is gossiped to the peer and the relationship downgrades immediately. This is exposed today over the token-gated control API:

POST /api/upgrade/request   { peerId, tier, scopes?, reason?, address? }
POST /api/upgrade/respond   { requestId, decision: approve|deny, scopes? }
GET  /api/relationships
POST /api/relationships/revoke  { peerId, grantId? }
GET  /api/notifications         # pending inbound/outbound requests
GET  /api/remote/peers          # peers who granted us administrative scope

A grant only authorizes the relationship; any privileged action layered on top (such as an SSH passthrough) still performs its own authentication.

Chat media transfer

Tier 2 unlocks media sharing in the web chat. Dropping one or more files onto an active chat either requests the Tier 2 media upgrade, or, when the relationship already has media:share, stages the files through the local daemon in disk-backed chunks. The sender then creates a media-offer control message over the existing end-to-end encrypted DM channel. The recipient sees an incoming file bubble and explicitly accepts or denies it. Only after acceptance does the sender push the bytes over the dedicated libp2p media stream:

/omnius/fabric/media/1.0.0

The media stream is authenticated against the libp2p peer id carried in the accepted offer's signed route. Files are sent as ordered chunks, reassembled to a .part file, and promoted only after the receiver verifies the byte count and SHA-256 hash from the offer. Received files are stored under the local data directory and downloaded through the token-gated loopback control API without buffering the whole file in memory. Images show an inline preview after receipt; all file types can be downloaded.

Media control API:

POST /api/media/offer       { peerId, filename, mime, dataBase64, address? }
POST /api/media/upload/start   { peerId, filename, mime, size, address? }
POST /api/media/upload/chunk?transferId=<id>&offset=<n>  raw bytes
POST /api/media/upload/finish  { transferId }
POST /api/media/accept      { transferId }
POST /api/media/deny        { transferId }
GET  /api/media/download/<transferId>

Bulk file transfer is intentionally gated on media:share; T0/T1 peers can still chat, but cannot offer files.

Signed route records

Every node periodically publishes a SignedRouteRecord to the DHT and GossipSub topics. The record is an Ed25519-signed JSON envelope:

schema: omnius:fabric:route-record:v1
peerId + optional nickname + signing + encryption public keys
directAddrs + relayAddrs (libp2p multiaddrs)
observedAddrs (what other peers see)
preferredRelays, capabilities, role, seq, issuedAt, expiresAt
Ed25519 signature over canonical JSON body

Records are stored in the DHT at /omnius/fabric/route/<peerId> and gossiped on topic /omnius/fabric/routes/1.0.0.

Install

npm install -g omnius-fabric

On first install, the package starts a background fabric node automatically. That node:

  • creates ~/.omnius-fabric/default
  • generates/persists Ed25519 + X25519 identity keys
  • starts a libp2p node (TCP + WebSocket transports, KadDHT, GossipSub)
  • attempts UPnP/NAT-PMP port mapping by default, and auto-serves as a relay if it succeeds
  • bootstraps off public NATS rendezvous by default; HTTPS manifests are opt-in
  • starts the NKN overlay by default and stores its seed under the data dir
  • publishes a signed route record to DHT + GossipSub
  • starts building peers.json as the local peerbook
  • writes state.json so fabric address / fabric status work from any shell
  • exposes a loopback HTTP control endpoint (token-gated) for fabric send / fabric connect / the web console

Upgrades replace the running daemon: the postinstall stops any stale fabric daemon (graceful SIGTERM, then SIGKILL) and spawns the new version, so a npm install -g omnius-fabric@latest never leaves an old process running outdated code.

Running daemons also self-check for npm releases. By default the daemon polls omnius-fabric@latest once per hour; when a newer version appears it starts npm install -g omnius-fabric@latest in the background. The package postinstall then stops the stale daemon and starts the freshly installed version with the same data directory, so the fabric stays current without a manual fabric stop && npm install && fabric start cycle. Status is exposed as autoUpdate in fabric status and in the web console.

Opt out of first-install background start:

OMNIUS_FABRIC_START_ON_INSTALL=0 npm install -g omnius-fabric

Opt out of daemon self-updates:

OMNIUS_FABRIC_AUTO_UPDATE=0 fabric start
fabric start --no-auto-update

Verify it is running

fabric status            # JSON daemon snapshot
fabric address           # just the fabric:// address
fabric peers             # learned peer book entries
fabric dht               # real KadDHT routing table (or peerbook fallback)
fabric doctor            # full diagnostics: libp2p, DHT, connections, bootstrap
fabric ui                # open the embedded dark-mode web console
fabric tui               # open the terminal-native console (also the no-arg default)
fabric stop              # gracefully terminate the daemon

Web console

Every daemon serves a self-contained single-page console on a loopback port. fabric ui prints (and opens) a one-time URL of the form http://127.0.0.1:<port>/?token=<token> — the page captures the token from the query string, strips it from the address bar, then talks to the daemon's token-gated control API. The control API is bound to 127.0.0.1 only, so other hosts on your LAN cannot reach it.

The console is a monochrome (black / mid-grey) SPA with:

  • a collapsible left sidebar with hash-routed tabs and a live endpoint list (UPnP, relay, Tor, NATS, NKN, KadDHT); the top-left brand shows the running omnius-fabric version
  • hash routes for every tab (#/status, #/peers, #/chat, #/sessions, #/connect, #/privileges, #/graph, #/settings, #/endpoint?kind=tor) with query-param deep-links (#/chat?peer=nf_…, #/connect?token=…)
  • clickable endpoint detail/config pages for libp2p, KadDHT, NATS, NKN, Tor, UPnP/NAT-PMP, and Circuit Relay. Long endpoint values such as .onion addresses are ellipsized in the sidebar and expanded on the detail page.
  • a Chat view with per-peer conversation panes, on-disk persistence, and transport-endpoint icons per peer. Peer nicknames advertised by the originator appear in chat and can be used as a search term.
  • message delivery details in chat: a small info icon next to each timestamp opens a hover card showing delivery state, transport, route, latency, and raw attempt strings (for example direct libp2p, route multiaddr, circuit relay, or NATS inbox fallback)
  • a connection upgrade dropdown in chat for requesting T1, T2, or T3, plus an inline approve/deny banner for inbound upgrade requests
  • Tier 2 media chat: attach or drag/drop one or more files/images/videos after a media:share upgrade, auto-request Tier 2 when media is not yet allowed, accept or deny inbound file offers, preview received images, and download accepted files. Large files use disk-backed chunk upload, chunked libp2p transfer, and SHA-256 reassembly verification.
  • a Sessions view with a quick request row: type a nickname, peer id, or full fabric:// address, send a session request, approve/deny inbound session requests, and cancel/delete pending or active sessions.
  • a Settings view to toggle UPnP, Tor, NATS (and its public defaults), NKN overlay settings, relay mode, capacity, bootstrap, manifest URLs, automatic update polling, and the node nickname — persisted to settings.json and applied on next restart
  • automatic update status in Node status, showing current version, latest observed version, last check, next check, and any update error
  • a Graph view: a three.js force-directed topology with monochrome splines and animated activity dots
  • topbar status pills (online / dht / upnp / nats / nkn)

Terminal UI

fabric tui opens a terminal-native console against the running daemon's loopback control API. Invoking fabric with no subcommand opens the same TUI when stdout is a TTY; if no daemon is running, it starts the background daemon first and then opens the TUI. Non-interactive shells still get command help.

The TUI is read/write where the control API supports it and otherwise mirrors the browser console with keyboard navigation:

  • status dashboard with online, DHT, UPnP, NATS, and NKN pills
  • peerbook table with nicknames, route counts, and last-seen data
  • chat peer list, transcript view, and encrypted DM composer
  • sessions and notifications views for rolling-encrypted session state
  • read-only settings summary for daemon configuration, including NKN state

REST and MCP agent surface

The loopback control port exposes a machine-readable REST catalog and a Model Context Protocol endpoint for agents. Both surfaces use the same one-time daemon token as the GUI:

Authorization: Bearer <token>
x-fabric-token: <token>
?token=<token>

REST discovery:

GET /api/capabilities     # REST catalog + MCP connection guidance
GET /api/rest             # alias for the catalog
GET /api/endpoints        # computed libp2p/upnp/relay/tor/nats/dht states
GET /api/endpoints/<kind> # endpoint detail for libp2p, upnp, relay, tor, nats, dht

The MCP streamable HTTP endpoint is:

POST /mcp

Initialize with protocol version 2025-11-25, then use tools/list, tools/call, resources/list, resources/read, resources/templates/list, prompts/list, and prompts/get. The server returns an MCP-Session-Id header on initialize, supports MCP-Protocol-Version: 2025-11-25, requires Accept: application/json, text/event-stream, supports JSON responses, single-event SSE responses, JSON-RPC batches, notification 202 Accepted responses, and DELETE /mcp session termination, validates browser Origin headers for the local endpoint, and exposes REST-equivalent tools for status, peers, sessions, chat, trust upgrades, media offer/accept, settings, privileges, WebRTC status, DHT, and endpoint diagnostics.

Agent guidance is available as both a resource and prompt:

resources/read omnius://guide
prompts/get    omnius-agent-guide

Transport-level encryption is handled by Noise (XX handshake, Curve25519, AEAD). Application payloads are additionally encrypted with the session ratchet (AES-256-GCM + HKDF-SHA512). Relay nodes cannot decrypt application data.

UPnP / NAT-PMP

The daemon attempts UPnP gateway discovery first, then NAT-PMP/PCP as a fallback (many consumer routers fail SSDP but answer NAT-PMP cleanly). The discovery budget is 30 s per protocol. The current mapping state is visible in fabric status and in the web console.

When UPnP succeeds, the mapped external address is added to the node's route record and published via DHT/GossipSub, making the node reachable from outside the local network. A reachable node also auto-serves circuit-relay reservations (relay mode defaults to both), so it immediately helps NATed peers join the fabric. The mapping maps the actual libp2p-bound TCP port, which can differ from the requested one if the port was taken at startup.

QR connect handshake (rolling-encrypted sessions)

The simplest path to a rolling-encrypted channel between two peers.

Issue an invite

fabric connect

fabric connect prints a scannable QR code in the terminal followed by a fabric+invite://… token. The invite contains:

  • the issuer's signed fabric:// address
  • a single-use 256-bit pre-shared key (PSK)
  • an X25519 ephemeral public key bound to this invite
  • a deterministic session id
  • issued/expires timestamps
  • an Ed25519 signature over the body

The PSK + ephemeral keys are stored locally under ~/.omnius-fabric/default/sessions/<sessionId>.json. The invite is consumed exactly once by the joiner.

Consume the invite

On the other peer:

fabric join 'fabric+invite://…'

This:

  1. Verifies the invite signature and freshness.
  2. Generates the joiner's own X25519 ephemeral keypair.
  3. Derives the session secret with HKDF-SHA512 over two Diffie-Hellman shared secrets (static×static + ephemeral×ephemeral) salted with the PSK.
  4. Saves a local session record with both directions of the ratchet chain key.
  5. Sends a signed session-claim envelope to the issuer through the libp2p DM protocol.

The issuer's running daemon recognises the claim, matches the session id, derives the same secret, marks the invite consumed, and emits a signed session-ack. From that moment both sides hold matching forward-secret chain keys.

Send rolling-encrypted messages

fabric sessions                       # list local sessions and their state
fabric send-session <sessionId> hello world

Each message advances a one-way HKDF ratchet: the chain key is overwritten after every send, so an attacker who compromises a chain key cannot decrypt prior messages. Inbound messages are dispatched by the running daemon and printed to its stdout/log.

Under the hood every session message is double-wrapped: the outer envelope is encrypted to the recipient's static X25519 identity (and signed with the sender's Ed25519 identity), and the inner payload is AES-256-GCM with the per-message ratchet key. A relay sees only the outer ciphertext.

Command name

Use the shorthand command:

fabric

The package also exposes the long bin:

omnius-fabric

One-node start

fabric start

The node will:

  • generate/persist an Ed25519 + X25519 identity under ~/.omnius-fabric/default
  • start a libp2p node (TCP + WebSocket, KadDHT, GossipSub, Circuit Relay, DCUtR)
  • attempt UPnP/NAT-PMP TCP port mapping automatically
  • join bootstrap discovery (HTTPS manifests, libp2p bootstrap) unless disabled
  • start the NKN overlay unless disabled, and publish an nkn route hint when the overlay address is ready
  • publish a signed route record to DHT + GossipSub
  • print a signed fabric:// address ticket
  • listen for encrypted inbound messages via libp2p DM protocol handler
  • discover peers via KadDHT, GossipSub, mDNS, and bootstrap
  • persist the local peerbook as it learns routes
  • write ~/.omnius-fabric/default/state.json so other shells can find it
  • expose a loopback HTTP control endpoint (token-gated) for fabric send/fabric connect
  • poll npm for new releases and replace the daemon automatically unless disabled

Run as a background daemon manually:

fabric start --daemon

Logs are written under:

~/.omnius-fabric/logs/

Relay mode

The daemon's circuit relay behaviour is controlled by --relay-mode. The default is both: any node that becomes reachable auto-serves relay reservations for peers that can't map a port, while still using other relays itself. NATed nodes pay no cost — no peer dials them for a reservation.

fabric start --relay-mode both            # host AND use relays (default)
fabric start --relay-mode server          # host reservations only
fabric start --relay-mode client          # connect via relays, don't host

With relay capacity (max concurrent reservations):

fabric start --relay-mode both --relay-capacity 16

Bootstrap discovery

By default, fabric start loads bootstrap peers from multiple sources:

  1. CLI flags: --relay, --nats (libp2p multiaddrs and/or NATS servers)
  2. env vars: OMNIUS_FABRIC_RELAYS, OMNIUS_FABRIC_NATS
  3. ~/.omnius-fabric/default/bootstrap.json
  4. HTTPS bootstrap manifests (opt-in via OMNIUS_FABRIC_BOOTSTRAP_URLS)
  5. libp2p bootstrap service (@libp2p/bootstrap with configured multiaddrs)
  6. public NATS rendezvous (demo.nats.io) — merged in by default for every node so DHT seeding works out of the box; runs in the background so daemon readiness is never gated on reaching it
  7. GossipSub peer exchange + pubsub peer discovery + DHT walking (once connected)

Public NATS is the primary cold-start seed because Omnius uses a custom DHT protocol — generic libp2p bootstrap nodes can't populate it. Run your own NATS for production reliability (Settings → NATS, or OMNIUS_FABRIC_NATS); demo.nats.io is a shared, rate-limited public mesh.

Disable the public defaults / bootstrap entirely:

fabric start --no-bootstrap              # isolated/local tests
OMNIUS_FABRIC_DEFAULT_NATS=0 fabric start # keep bootstrap, drop public NATS

NKN overlay fallback

NKN is enabled by default as an additional p2p delivery path. The daemon creates or reuses a persistent seed at <dataDir>/nkn-seed, starts an nkn-sdk MultiClient with the omnius identifier and four sub-clients, and reports live overlay state in fabric status under nkn.

When the NKN client connects early enough during startup, the daemon includes an unexpired route hint like this in the signed fabric:// address:

{ "type": "nkn", "role": "nkn", "url": "omnius.<pubkey-hex>", "score": 70 }

Delivery still prefers direct libp2p routes, relay/DCUtR, and NATS inboxes first. NKN is tried after those paths as a universal fallback for peers whose signed address contains an nkn hint. The payload is the same signed, end-to-end encrypted envelope used everywhere else; NKN nodes route opaque ciphertext.

Disable NKN for isolated tests or private/offline deployments:

fabric start --no-nkn

Two-node workflow (no QR)

Terminal A:

fabric start

Copy the printed fabric://... address.

Terminal B:

fabric send 'fabric://PASTE_ADDRESS_FROM_A' 'hello from B'

Terminal A receives and decrypts the message. The daemon delivers it via the libp2p DM protocol (/omnius/fabric/dm/1.0.0) using the peer's multiaddrs from the address ticket.

Three-node fabric workflow

Node A acts as a full node and also as a reachable relay server:

fabric start --port 7766 --relay-mode both

Nodes B and C join A as relay clients:

fabric start --relay ws://YOUR_PUBLIC_HOST_OR_IP:7766

All three now:

  • register signed route records in DHT + GossipSub
  • discover each other via KadDHT walking, GossipSub peer exchange, and relay discovery
  • persist learned peers in peers.json
  • can send encrypted messages through direct or relay routes

Inspect learned peers:

fabric peers

Inspect real KadDHT routing table:

fabric dht

Run full diagnostics:

fabric doctor

Send to a full address:

fabric send 'fabric://...' 'message'

Send to a learned peer ID:

fabric send nf_abc123... 'message'

Diagnostics

The doctor command runs comprehensive diagnostics against the running daemon:

fabric doctor

Output includes:

{
  "running": true,
  "dataDir": "/home/user/.omnius-fabric/default",
  "diagnostics": {
    "startedAt": 1716800000000,
    "pid": 12345,
    "peerId": "nf_abc123...",
    "multiaddrs": ["/ip4/192.168.1.5/tcp/7766", "/ip4/127.0.0.1/tcp/7767/ws"],
    "connections": 3,
    "dht": {
      "ready": true,
      "routingTableSize": 8,
      "peersInTable": ["12D3K...", "16Uiu2..."],
      "mode": "server"
    },
    "bootstrap": {
      "sources": ["static-config", "default nats (public bootstrap)"],
      "peerCount": 5,
      "errors": []
    },
    "controlPort": 7765,
    "upnp": { "ok": true, "externalAddress": "203.0.113.5", "protocol": "nat-pmp" },
    "tor": { "available": true, "onionAddress": "...", "socksPort": 9050 },
    "nkn": {
      "enabled": true,
      "connected": true,
      "address": "omnius.<pubkey-hex>",
      "identifier": "omnius",
      "numSubClients": 4
    }
  }
}

The dht command provides a quick view of KadDHT state, or falls back to peerbook data when no daemon is running:

fabric dht

Autostart

Enable user-level autostart:

fabric autostart enable

With relay/NATS hints:

fabric autostart enable --relay ws://seed.example.com:7766 --nats nats://seed.example.com:4222

Status:

fabric autostart status

Disable:

fabric autostart disable

Autostart targets:

  • Windows: Startup .cmd
  • macOS: user LaunchAgent
  • Linux: user systemd service file

Linux note: after enabling, run the command printed by the CLI, usually:

systemctl --user daemon-reload && systemctl --user enable --now omnius-fabric.service

Environment variables

OMNIUS_FABRIC_START_ON_INSTALL=0   disable postinstall background start
OMNIUS_FABRIC_DEFAULT_NATS=0       disable default NATS discovery
OMNIUS_FABRIC_BOOTSTRAP=0          disable all automatic bootstrap config
OMNIUS_FABRIC_RELAYS=ws://host:7766,ws://host2:7766
OMNIUS_FABRIC_NATS=nats://host:4222,nats://host2:4222
OMNIUS_FABRIC_NATS_SUBJECT=omnius.fabric.routes

Legacy aliases are also accepted:

FABRIC_START_ON_INSTALL
FABRIC_DEFAULT_NATS
FABRIC_BOOTSTRAP
FABRIC_RELAYS
FABRIC_NATS
FABRIC_NATS_SUBJECT

Persisted configuration

Beyond env vars and one-off CLI flags, the daemon persists preferences to ~/.omnius-fabric/<data>/settings.json (mode 0600). The Settings tab in the web console reads and writes these; a CLI flag always overrides the persisted value for that one invocation. Changes apply on the next daemon restart — libp2p services are configured at startup and can't be hot-swapped.

| Setting | Default | Effect | |---|---|---| | nickname | "" | Public node display name advertised in signed addresses and route records | | upnpEnabled | true | Attempt UPnP/NAT-PMP port mapping | | relayMode | both | Circuit-relay role: client / server / both | | relayCapacity | 16 | Max concurrent relay reservations | | autoRelayOnReachable | true | Auto-host relay once publicly reachable | | torEnabled | false | Spawn a Tor onion hidden service | | useDefaultNats | true | Merge the public NATS rendezvous for bootstrap | | natsServers | [] | Operator NATS servers (added on top of defaults) | | nknEnabled | true | Start the NKN overlay and advertise an nkn route hint when connected | | nknIdentifier | omnius | Prefix for this node's NKN address (<identifier>.<pubkey-hex>) | | nknNumSubClients | 4 | NKN MultiClient sub-client count for overlay reliability | | nknRpcServers | [] | Explicit NKN RPC servers; empty uses NKN mainnet defaults | | bootstrapEnabled | true | Load relay/NATS/manifest bootstrap on start | | port | 7766 | libp2p listen port | | remoteShellEnabled | false | Master switch for administrative passthrough (off by default) |

Acceptance tests

npm run test:local

This runs:

node dist/cli.js test-local
node dist/cli.js test-triad
node dist/cli.js test-bootstrap-config
node dist/cli.js test-connect

test-local proves: libp2p node starts, KadDHT reports status, multiaddrs are announced.

test-triad proves: three libp2p nodes start and verify all are running.

test-bootstrap-config proves: first-run bootstrap discovery loads by default and can be disabled.

test-connect proves: invite creation, session key derivation, and ratchet encryption round-trip verified.

Additional local validation used for the web media path starts two runtimes, requests and approves a Tier 2 relationship, stages a file through the chunk-upload API, sends a file offer, accepts it, pushes the chunked media stream, verifies reassembly, and downloads the received file through the control API.

Recent TUI and NKN validation:

npm run build
node dist/cli.js --help
node dist/cli.js start --help
node dist/cli.js start --foreground --port 0 --host 127.0.0.1 --no-upnp --no-bootstrap --no-auto-update

npm run build type-checks and compiles the terminal UI, NKN transport, and runtime/status/settings integration. The local acceptance tests pass nkn: false internally for deterministic offline runs; live NKN validation is a daemon smoke check. With a default start, fabric status should include nkn.enabled, nkn.connected, nkn.address, and nkn.identifier; when the overlay connects before the first address publish, fabric inspect "$(fabric address)" shows a route with "type": "nkn". fabric tui validates the terminal console against the same token-gated control API used by the browser console.

Security model

Omnius Fabric uses two layers of encryption:

Layer 1: Transport (libp2p Noise)

  • Noise XX handshake with Curve25519 key agreement
  • AEAD (AES-256-GCM or ChaCha20-Poly1305) per-packet encryption
  • Authenticates both sides of every connection
  • Relay nodes see only Noise-encrypted streams — they cannot inspect payloads

Layer 2: Application (Session Ratchet)

  • X25519 static + ephemeral key agreement
  • HKDF-SHA512 key derivation from two Diffie-Hellman shared secrets
  • AES-256-GCM per-message encryption with rolling ratchet keys
  • Forward secrecy: chain key is overwritten after each send

Route records

  • Ed25519 signatures over canonical JSON bodies
  • Signed fabric:// address tickets
  • TTL/replay-expiry fields (default 24h)

Trust and media

  • T1/T2/T3 upgrades are double-signed by both peers and expire.
  • T2 grants include media:share; media offers still require recipient acceptance before any bytes are transferred.
  • Media bytes travel over a dedicated libp2p stream only after acceptance, are checked against the offered SHA-256 digest, and are served to the local browser through the token-gated loopback API.
  • T3 grants include administrative scopes such as shell:exec, but privileged features remain disabled unless their own local settings and authentication checks also pass.

Primitives

  • Ed25519 identity/signatures
  • X25519 key agreement
  • HKDF-SHA512 key derivation
  • double AES-256-GCM payload encryption (Noise transport + application ratchet)
  • signed route records + invite tokens
  • double-signed trust grants and revocations
  • SHA-256 verification for accepted media transfers
  • TTL/replay-expiry fields

Rolling session forward secrecy

Session secret = HKDF-SHA512(static×static ‖ ephem×ephem, salt = invite PSK, info = sessionId)
Per-direction chain key K0 = HKDF(secret, info = "chain:v1:role")
For message n: (msgKey_n, K_{n+1}) = HKDF(K_n, info = "ratchet:v1")
K_n is overwritten with K_{n+1} after each send — the old key is gone.
Replay rejected by counter monotonicity.

Relays can see routing metadata such as connection timing, approximate sizes, and destination peer IDs. They cannot decrypt Noise transport payloads (layer 1), and they cannot derive session secrets (layer 2) without one side's static or ephemeral private key.

Guarantee boundary

Valid claim:

If a recipient's fabric:// address contains at least one route reachable by the sender,
the sender can deliver an end-to-end encrypted message to that recipient.

Fabric claim:

As more users run the package, reachable nodes automatically become relay nodes,
private nodes reserve relay paths, and KadDHT/GossipSub route propagation compounds
peer knowledge across the network.

Invalid claim:

Two isolated devices behind arbitrary hostile NATs can connect with zero reachable third-party path.

A cooperative reachable relay path is required for hostile NAT/CGNAT/corporate networks. Circuit Relay v2 + DCUtR handles most consumer NAT scenarios.

Commands

fabric start [--port N] [--host HOST] [--public-url URL]
            [--relay URLS] [--nats SERVERS] [--nats-subject SUBJECT]
            [--relay-mode client|server|both] [--relay-capacity N]
            [--daemon] [--foreground] [--daemon-child]
            [--no-server] [--no-upnp] [--no-tor] [--no-bootstrap]
            [--no-auto-update] [--no-nkn]
fabric stop [--force]
fabric address
fabric status
fabric doctor
fabric dht
fabric peers
fabric ui [--print]
fabric tui
fabric connect [--ttl-minutes N] [--label TEXT] [--no-qr]
fabric join <fabric+invite://...>
fabric send-session <sessionId> <message>
fabric sessions
fabric send <fabric://address|peerId> <message>
fabric inspect <fabric://address>
fabric autostart enable|disable|status
fabric test-local
fabric test-triad
fabric test-bootstrap-config
fabric test-connect

Media transfer is currently exposed through the web console and local control API rather than a dedicated CLI command.