The Problem
Enterprises and power users need a privacy‑first, decentralized network that can traverse firewalls and NAT without relying on a central cloud. Existing VPN or SD‑WAN solutions either expose traffic to a single provider or require heavyweight infrastructure.
What This Does
ztm implements a software‑defined mesh built on HTTP/2 tunnels, providing end‑to‑end TLS and certificate‑based identity. The repository is a portfolio of five self‑contained projects:
- gui – the desktop UI (Vite + Tauri) under
gui/. Core UI logic lives ingui/src/service/ZtmService.js(28 functions) andgui/src/service/common/request.js(29 functions) which wrap network calls. - agent – the runtime daemon (
agent/main.js,agent/mesh.js). It handles peer discovery, NAT traversal (agent/nat.js), and proxy stitching. - cli – thin command‑line wrappers (
cli/main.js, 80 functions) that invoke the same agent APIs. - hub – a minimal orchestration entry point (
hub/main.js). - ca – Certificate Authority utilities (
ca/).
All projects share a common request layer (gui/src/service/common/request.js) that issues HTTP calls via axios. The UI, daemon, and CLI ultimately call the same service functions, e.g. request.getUrl, request.postWithStream, and agent/api.js helpers like findMesh and init.
How It Is Wired
Execution begins at the binary produced by the CLI or the GUI. For the CLI the entry point is cli/main.js → main() (line 6) which parses arguments and dispatches to sub‑commands such as agent/apps/ztm/chat/cli.js → main() → doCommand().
cli/main.jscallsagent/api.js(init,findMesh) andagent/mesh.js(connectProxy,makeInitRequest).agent/mesh.js(125 functions) is the most connected module: it reads/writes files, makes outbound network calls, and is called from 11 other files.- The request flow that touches the outside world is:
cli/main.js→agent/api.init→agent/mesh.connectProxy→gui/src/service/common/request.getUrl→axios.get(...). This path involves four distinct hops before a network request leaves the process. - The UI follows a similar chain: UI actions invoke
ZtmService.login(ingui/src/service/ZtmService.js), which callsrequest.postWithStream, ultimately reaching the sameaxioslayer.
The internal call graph shows request being invoked from 104 distinct locations, making it a high‑blast‑radius function. Conversely, agent/fs.js (10 functions) handles local persistence without network impact and is called from nine places.
No circular import cycles were detected, which simplifies static reasoning. However, deep nesting (max depth 8) and duplicated CLI scaffolding across agent/apps/ztm/*/cli.js increase cognitive load.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/ztm
cd ztm
# Install JavaScript dependencies
npm ci # uses package-lock.json
# Build the desktop UI (requires Rust/Tauri)
cd gui
npm run build # invokes Vite + Tauri build defined in gui/apps/.../vite.config.js
# Run the CLI (example: start a chat service)
node cli/main.js chat --help
Configuration files are expected under gui/.env (currently committed – see health notes). The daemon reads its identity from files managed by agent/fs.js and agent/ca/ utilities.
Real‑World Use
A remote‑worker could install the CLI on a laptop, run node cli/main.js tunnel start --mesh prod, and have the daemon create an HTTP/2 tunnel to a corporate hub. The hub (hub/main.js) accepts the connection, authenticates via the certificate chain, and routes traffic to internal services without exposing them to the public Internet.
Code Health & Issues
- High – Pin GitHub Actions –
.github/workflows/*.ymluse version tags (e.g.Swisyn/setup-android-sdk@v1). Replace with commit SHAs. - High – No test suite – 283 source files, zero test files. Add tests for each public entry point.
- High – Committed
.env–gui/.envandgui/.env.developmentcontain secrets. Remove, git‑ignore, and rotate credentials. - High – Eval over runtime value –
cli/main.jsexecutesexec()on a computed string. Refactor to explicit parsing. - Medium – Least‑privilege GITHUB_TOKEN – workflows lack
permissions:blocks. Declare minimal scopes. - Medium – Enable Dependabot – no dependabot config; add
.github/dependabot.yml. - Medium – Pin Docker base image –
build/docker/Dockerfileuses mutabledebian:12-slim. Pin by digest. - Medium – Dependency‑vulnerability gate – CI lacks a scan step; add
dependency-review-actionorosv-scanner. - Medium – Pre‑commit secret scan – No secret‑gate; add a pre‑commit hook (e.g.
git-secrets). - Medium – Checkout persist‑credentials – set
persist-credentials: falsein Android build workflow.
Additional observations: the repository includes a license file, CI via GitHub Actions, and a Dockerfile, but the presence of committed secrets and lack of tests are critical blockers for production use.
The Bottom Line
ztm delivers a functional, cross‑platform mesh built on HTTP/2 and TLS, with a clear separation between UI, daemon, and CLI. The codebase is large and loosely organized, showing deep nesting and duplicated CLI scaffolding that hamper maintainability. Security hygiene needs immediate attention (committed secrets, eval usage, unpinned actions). Suitable for teams willing to invest in refactoring and testing; not ready for unmodified production deployment.