edge-toolkit is a WebSocket-based edge-computing framework that runs AI on hardware you control, so nothing has to leave your network. A lightweight server acts as a hub that serves small AI modules — written in Rust, Python, Dart, C#, Java and more, each compiled to WebAssembly or transpiled to JavaScript — straight to a browser, where they run locally and can reach the browser's own Web APIs (camera, microphone, geolocation, motion sensors, Bluetooth, NFC) to sense the real world directly. The same framework also drives larger models on local GPU hardware through standardised WebAssembly interfaces, so one toolkit spans on-device and server inference without changing the protocol.
The result is AI that protects privacy and data sovereignty: sensitive camera, audio and research data stay on the device or your own network, never sent to an external cloud service.
Please install mise (2026.6.5 or later),
including the shell integration.
It is needed for all use of this repository.
The mise configuration lives under .mise/: the always-loaded
.mise/config.toml holds the Rust/Node tooling and shared
tasks, and per-language .mise/config.<lang>.toml files (dart, dotnet, java,
python, zig) are selected via MISE_ENV so a dev can work on one language
without installing the others — e.g. MISE_ENV=dart mise install. CI runs
every language; mise run check-all (and install-all, test-all, …) act on
all of them at once.
The following works for Linux, macOS and Windows, and all tools "installed" are only installed into the local workspace, so no need for admin/root privileges.
Then run the preinstall task for your platform — it configures mise and installs the shared basics (cargo-binstall, node, the openssl dev files) plus whatever that platform needs. Do any manual prerequisites in your platform's section below first.
mise install downloads many tools from GitHub releases, which are subject to
GitHub's REST API rate limits.
Unauthenticated requests share a low per-IP limit, so installs can fail with
GitHub rate limit exceeded. Authenticate with the
gh CLI and let mise reuse its token — this raises
the limit and needs no token scopes:
mise install ghgh auth login # any method; no scopes needed
mise settings set github.credential_command "gh auth token"
mise token github # verify: should resolve a tokengh often stores the token in the OS keyring rather than in
~/.config/gh/hosts.yml, so mise's default hosts.yml lookup finds nothing;
credential_command asks gh for the token on demand and works either way. The
setting is written to your global ~/.config/mise/config.toml, so it stays
per-machine and out of the repo.
mise.exe links the Microsoft VC++ runtime (vcruntime140.dll), so it must be
present or mise won't start. It's preinstalled on Windows 10/11 and Server, so
you already have it — only Nano Server omits it, and there the Docker build
installs the VC++ Redistributable.
On Windows, install the shell:
mise install http:busyboxTo install dependencies:
mise run preinstall
mise install-allThe preinstall task will advise if there are any required dependencies are
are missing, such as Xcode Command Line Tools on MacOS.
mise install runs tool installs in parallel. If they fail intermittently — a
download race, or a cargo: source build colliding with another — serialize
them with MISE_JOBS=1:
MISE_JOBS=1 mise install-allThis is the same workaround both Docker builds bake in, so reach for it first if a local install or build misbehaves.
Use mise run fmt-all and mise run check-all to run formatters and checkers.
Dockerfile reproduces the mise setup above on a clean, minimal
Ubuntu, in stages (build → prefetch → precompile → test/server). A
plain build produces the server image (the final stage): a release build of
et-ws-server, served automatically. mise install-all fetches many tools from
GitHub releases, so build with a GitHub token to avoid the anonymous rate limit
(see GitHub rate limits), passed as a BuildKit secret so
it never lands in an image layer:
GITHUB_TOKEN="$(gh auth token)" DOCKER_BUILDKIT=1 \
docker build --secret id=gh_token,env=GITHUB_TOKEN -t edge-toolkit .
docker run --rm -p 8080:8080 edge-toolkitThen open http://localhost:8080 (add -p 8443:8443 for TLS). The server needs
no GPU. OpenObserve/o2 is optional — OTLP export is off when no collector is
configured. (Drop --secret to build without a token; install-all may then hit
rate limits.)
The full test suite is a separate, non-final stage, so build it explicitly
with --target test. The WebGPU compute test needs a GPU, and docker build
can't attach one (no --gpus for build), so it runs at docker run time. The
test stage bundles mesa-vulkan-drivers, so passing the host DRI node gives
wgpu a real Intel/AMD GPU (and a software fallback if you pass nothing):
docker build --target test -t edge-toolkit-test .
docker run --rm --device /dev/dri edge-toolkit-test # Intel/AMD GPUNVIDIA via --gpus all (with the NVIDIA Container Toolkit) is wired but
unverified — its in-container Vulkan ICD doesn't initialize yet, so prefer a
DRI device. The image skips the o2/ws-server README steps (runtime services).
The docker-linux and
docker-windows workflows rebuild these
images when their respective Dockerfile is modified.
Dockerfile.nanoserver starts from Nano Server
(the smallest Windows base, ~120 MB) — which has no installer stack, or shell.
A gh_token file (a GitHub token) in the build context is optional for a
manual Dockerfile.nanoserver build — without it, mise uses GitHub's anonymous
rate limit and may be throttled. The classic Windows builder has no BuildKit
secrets, so it bakes that file into an image layer: never
publish an image built with a gh_token. (The Linux build passes the token as a
BuildKit secret instead, so it never lands in a layer.)
In a separate terminal start OpenObserve (o2) and leave it running.
mise run o2Then start the fetch the ONNX models and run the server
mise run download-models
mise run build-modules-all
mise run ws-serverScan the QR-Code with a smart-phone camera and open the URL.
Select the module to run in the drop-down, then click "Run module" button.
Note: The WASM build disables WebAssembly reference types, so it can still load on older browsers such as Chrome 95.
In a separate terminal, open the OpenObserve UX using:
mise run open-o2The server logs appear in the Logs section.
The module list is dynamically populated from the modules in services/ws-modules.
Each module must have a package.json that defines a main which contains a JavaScript file
that can load and run the module.
Under each module in ws-modules, the package can be found in a subdirectory pkg.
Most of the module are built from Rust using wasm-pack build --target web.
There are also modules written in:
- Dart
- Java
- .Net C#
- Python, using pyodide
- Zig, including C code.
The default UX in the web-browser is also a loadable module located in services/ws-server/static.
A custom UX module can be used by setting the ws-server environment variable MODULES_ROOT.
The WebSocket protocol and the ws-server REST surface are described by
machine-readable specs regenerated from their Rust sources of truth by
mise run gen-specs-all:
- WebSocket (AsyncAPI 3.0):
generated/specs/ws.yaml. Source:ClientMessage+ServerMessageinlibs/edge-toolkit/src/ws.rs. Generated clients:generated/dart-ws/,generated/python-ws/, and theet:ws-messagesWIT undergenerated/specs/wit/deps/. - REST (OpenAPI 3.0):
generated/specs/rest.yaml. Source:#[utoipa::path]annotations on the handlers inservices/{ws-server,modules,storage}. Typed Rust client atgenerated/rust-rest/(consumed byet-ws-wasi-runnerand the browserdata1module).
See generated/README.md for a full catalogue
of what's regenerated vs. hand-maintained under generated/.
Run the end-to-end tests using Chrome:
mise run ws-e2e-chromeRun an example demo scenario using et-cli
cargo install --path utilities/cli --force
et-cli generate-deployment \
--input-file verification/local/input/facility-security-scenario.yaml \
--output-dir verification/local/output/facility-security-scenarioThis will generate a mise.toml file under
verification/local/output/facility-security-scenario. Run the following
command to start the demo scenario:
mise run generated-scenarioTo generate a Docker Compose deployment instead, pass
--output-type docker-compose or set deployment_type: docker-compose in the
scenario input YAML. This writes compose.yaml to the output directory:
et-cli generate-deployment \
--input-file verification/local/input/facility-security-scenario.yaml \
--output-dir verification/local/output/facility-security-scenario \
--output-type docker-compose
cd verification/local/output/facility-security-scenario
docker compose up --buildThe generated scenario config only selects which prebuilt modules ws-server
serves. Module builds are expected to be handled separately from the repository
root.
To regenerate all checked-in verification outputs from
verification/*/input, writing each scenario to
the matching verification/*/output/<input-file-stem> folder. This generates
all supported deployment files for each scenario, currently mise.toml and
compose.yaml:
mise run regen-verificationThis repository is part of a grant managed by the School of EECMS, Curtin University.
ABN 99 143 842 569.
CRICOS Provider Code 00301J.
TEQSA PRV12158