Quickstart: deploy an app
This walks you through deploying the canonical hello-tabbify example: package it with tcli, let a supervisor host it as a per-app runner, and proxy a request to it through the public node. Everything here is the shipped Phase-1 path — tcli push → S3 → supervisor → runner → node.
Push the app
The example is a WASI-HTTP component with a manifest.toml declaring runtime wasm-http and entry app.wasm. tcli push mints a UUID v7 on first push (recorded in tabbify.lock), bumps the version on every push after, stamps the app id into the manifest, and uploads to the tabbify-apps S3 bucket:
tcli push examples/hello-tabbify
# Resolved identity from tabbify.lock: uuid=0191e7c2-..., version=1
# Planning upload to s3://tabbify-apps/apps/0191e7c2-.../v2/
# Wrote latest marker: 2
Artifacts land under apps/<uuid>/v<N>/ with a latest text marker that is the canonical version number. Use --dry-run to plan without touching AWS — but note it still advances tabbify.lock, so don't run it repeatedly. AWS credentials come from the standard chain (env → ~/.aws/credentials → SSO → instance role).
Start it on a supervisor
Ask the node which supervisors are in the mesh, then start your app on one. The node aggregates app inventory across every supervisor and proxies lifecycle calls to whichever one will host it. All authenticated calls need the bearer key (tabbify-dev-node-key is the RnD default):
curl -H 'Authorization: Bearer tabbify-dev-node-key' \
http://3.124.69.92:8090/v1/supervisors
curl -X POST -H 'Authorization: Bearer tabbify-dev-node-key' \
http://3.124.69.92:8090/v1/apps/0191e7c2-1111-7222-8333-444455556666/start
# {"state":"running","app_ula":"fd5a:1f02:...::1","supervisor_ula":"fd5a:1f00:1::1"}
The supervisor spawns a detached tabbify-runner for the app. That runner joins the mesh as its own peer on a deterministic ULA — fd5a:1f02:<blake3(uuid)[0:6]>::1, stable across restarts and hosts — and serves on [app_ula]:8730.
Reach it through the node
Hit /app/<uuid>. The node derives the same app-ULA from the UUID and dials it directly over the mesh, streaming the response back:
curl http://3.124.69.92:8090/app/0191e7c2-1111-7222-8333-444455556666 \
-H 'Authorization: Bearer tabbify-dev-node-key'
# 200 OK "Hello, Tabbify!"
When you're done, stop the instance (artifacts stay cached for a fast restart):
curl -X POST -H 'Authorization: Bearer tabbify-dev-node-key' \
http://3.124.69.92:8090/v1/apps/0191e7c2-1111-7222-8333-444455556666/stop
Notes and next steps
The node runs on port 8090, not 8080 — auth occupies 8080 on the same host. The bearer key is a hardcoded RnD default; set TABBIFY_NODE_KEY to a long random secret for any shared deployment. Mesh routing is IPv6 ULA over WireGuard, so the supervisor and runner need NET_ADMIN + /dev/net/tun.
Next: read the tabbify.toml manifest for the unified config format, the deploy pipeline to deploy straight from a git push, the CLI reference for all of tcli, and the node API for REST + MCP. To run your own supervisor, see self-hosting a node.