Documentation
ReferenceArchitecture

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/
FlagEnvDefault
--bucketTABBIFY_APPS_BUCKETtabbify-apps
--regionTABBIFY_APPS_REGIONeu-central-1
--dry-runoff

--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.