CLI reference (tcli)
tcli is the Tabbify app-layer CLI. It packages a local app directory and
publishes it to the tabbify-apps S3 bucket, launches a supervisor node from a
node.toml, and keeps itself current. The binary is tcli; all logic lives in
the tabbify_cli library so it stays unit-tested.
There are exactly three top-level subcommands: push, node up, and
self-update. tcli --version prints the build-stamped version (from the git
v* tag).
push
Package an app directory and publish it to the tabbify-apps S3 bucket.
tcli push <app-dir> [--bucket <name>] [--region <r>] [--dry-run]
push resolves the app's identity from <app-dir>/tabbify.lock — absent mints a
fresh UUID v7 (version 1), present reuses the id and bumps to latest + 1 — then
writes the bumped lock back so you never hand-write the UUID. It uploads every
file except tabbify.lock, target/, and .git/ to
s3://<bucket>/apps/<uuid>/v<N>/, then writes the apps/<uuid>/latest text
marker (the canonical version). For a Docker app it builds the image first; for a
WASM app it ships the entry component as-is.
tcli push examples/hello-tabbify
# Resolved identity: uuid=0191e7c2-..., version=2
# Planning upload to s3://tabbify-apps/apps/0191e7c2-.../v2/
| Flag | Env | Default |
|---|---|---|
--bucket | TABBIFY_APPS_BUCKET | tabbify-apps |
--region | TABBIFY_APPS_REGION | eu-central-1 |
--dry-run | — | off |
--dry-run plans and prints the keys without any PutObject, but still
advances tabbify.lock — versions are monotonic, so don't run it in a loop. A
real push uploads via the default AWS credential chain and needs
s3:PutObject on tabbify-apps/apps/*.
Which manifest push reads
Migration is in flight. push prefers <app-dir>/tabbify.toml; if it's absent
it falls back to the legacy manifest.toml and synthesizes a unified manifest
from it (runtime.type = "wasm-http" → build.kind = wasm, otherwise
docker). When a tabbify.toml is present, push materializes a derived
manifest.toml so the upload layer carries the correct runtime and lifecycle.
Field-by-field detail is in the tabbify.toml manifest.
node up
Launch a supervisor node from a node.toml deployment manifest.
tcli node up -f node.toml [--dry-run]
node up parses node.toml and materializes the docker run argv for
tabbify-supervisor: it always wires the mesh transport
(--device /dev/net/tun --cap-add NET_ADMIN), a persistent
<name>-state:/var/lib/tabbify volume, and SUPERVISOR_NAME. Capability tables
add --device /dev/kvm (Firecracker) and the Docker socket plus --network host
(Docker-in-Docker). --dry-run prints the command instead of running it.
# node.toml
[node]
name = "edge-fra-1"
[backend]
type = "docker" # only "docker" is implemented; "firecracker" errors
restart = "unless-stopped"
[artifact]
image = "ghcr.io/tabbify-io/tabbify-supervisor:latest"
[capabilities]
firecracker = true
docker = true
[mesh]
coordinator = "http://3.124.69.92:8888"
[resources]
cpus = 4
memory_mb = 8192
The backend.type = "firecracker" path is staged — it returns a clear "not yet
implemented" error today; only the docker backend builds an argv. See
self-hosting a node.
self-update
Replace the running tcli with the latest published release.
tcli self-update [--check] [--base-url <url>]
It reads the cli/latest JSON manifest, compares the build-stamped version
against latest, downloads cli/v<VER>/tcli, verifies the manifest's sha256,
atomically swaps the binary, and keeps the old one under
~/.tabbify/versions/<old>/tcli. --check only reports whether a newer version
exists. --base-url (env TABBIFY_CLI_BASE_URL) overrides the release prefix.
tcli self-update --check
# update available: v1.3.0 -> v1.4.0 (run `tcli self-update`)
Next steps
New to the platform? Start with the quickstart for the full
push → supervisor → node round trip, then read
the tabbify.toml manifest for the config push consumes.