Reference

CLI reference

Every command group, global flag, and the common flows.

The CLI is a single binary, ant. Five groups cover the surface: Build (ant haul), Deploy (ant trail), the machine layer (ant nest), Collab (ant colony), and the dashboard service (ant ui).

The obvious verbs are aliases for the group paths, so a first guess works: ant deploy|logs|status|down|restart|destroy|rollback|history|prune → ant trail …; ant build → ant haul; ant init|new|edit|machines|tools|templates|identity|groups → ant nest …; ant account → ant colony; ant dashboard → ant ui.

Shell completion is available for every shell Cobra supports:

ant completion bash > /etc/bash_completion.d/ant
ant completion zsh  > "${fpath[1]}/_ant"
ant completion fish > ~/.config/fish/completions/ant.fish

Global flags

These are accepted by every command (persistent flags on the root; --config is added to each command that reads ant.yaml):

FlagEffect
--machine <id>Operate on another machine (default local). Honoured by machine-scoped commands; commands that only act on this host fail fast when it targets a remote, and the machine registry ignores it. ANT_MACHINE is the environment fallback, so a CI pipeline can set the target once.
--config <path>Path to ant.yaml (default ant.yaml). On commands that read a project config.
--verboseEcho each child command ($ docker compose … build) before running it
-q, --quietSuppress progress and build output; only results print
-h, --helpHelp for the command
-v, --version (root) or ant versionPrint the CLI version

Commands that report data also take --json. Build output streams to stderr, so --json output on stdout stays machine-readable.

ant haul, build

ant haul                          # build for deployment "local"
ant haul dev
ant haul --release 20260101T120000Z

Flags: --release <id> (build tag, default a UTC timestamp), --push (build here and push to deploy.registry without deploying, the split-pipeline form for CI), --config.

Builds the image without running it (build: none is rejected). A project that names a machine builds on that machine; compose projects build here, where the source is. --push always builds here and supports container projects only.

ant trail, deploy and manage

ant trail deploy                  [deployment] [--no-caddy] [--release ID]
ant trail deploy --image REF      [--from-tar F | --pull] [--port P] [--domain D]... [--machine M]
ant trail logs                    [deployment] [service] [-f] [--tail N]
ant trail status                  [deployment] [--json] [--machine M]
ant trail restart                 [deployment]
ant trail down                    [deployment]
ant trail destroy                 [deployment] --yes [--keep-images] [--machine M]
ant trail exec                    [deployment] -- <command> [args...]   [--service NAME]
ant trail env                     [deployment]
ant trail doctor                  [deployment]
ant trail prune                   [--all] [--images] [--dangling] [--cache] [--volumes] [--stopped] [--dry-run] [--yes]
ant trail history                 [--project P] [--machine M] [--limit N] [--json]
ant trail history --clear         [--project P] [--yes]
ant trail rollback                [deployment] [--to RELEASE] [--steps N]

Flags by command:

CommandFlags
deploy [deployment]--no-caddy, --release <id>, --deploy-timeout <d>, --json
deploy --image REF--image, --app, --name, --from-tar <file>, --pull, --port <n>, --env KEY=VALUE (repeatable), --domain D (repeatable), --network, --restart (default unless-stopped), --publish-all, --timeout (default 5m)
logs [deployment] [service]-f/--follow, --tail <n>
status [deployment]--json
exec [deployment] -- cmd--service <name> (compose only); local deployments only
destroy [deployment]--yes, --keep-images; on a machine it removes the workload (container/compose/stack) and its domains, leaving the machine's images for cache
prune--all; per-category --images/--skip-images, --dangling/--skip-dangling, --cache/--skip-cache, --volumes/--skip-volumes, --stopped/--skip-stopped; --app, --deployment (default local), --keep-images <n>, --dry-run, --yes
history--project, --machine, --limit (default 20), --json, --clear, --yes
rollback [deployment]--to <release-or-image>, --steps <n> (default 1), --json

A machine: field in ant.yaml makes deploy remote: the client packages the build context (honouring .dockerignore), the machine builds the image there, runs it, and programs the machine's Caddy, which is required on a remote nest. No image is transferred for a project deploy; ant trail deploy --image is the low-level form for running a pre-built image (--from-tar uploads a docker save archive, --pull fetches from a registry).

On a machine, a deploy stages the new container (ephemeral ports, read-only mounts only), waits for the configured health_check, and only then swaps: a bad build does not take the running container down. A deploy whose mounts are writable (a live data volume or a bind the app needs to boot) cannot be staged safely and is replaced in place instead. Remote deploys default to restart: unless-stopped, apply log rotation and resource limits even when unset, and prune superseded image tags to deploy.keep_images (or rollback.keep_releases). Concurrent deploys on a machine are serialized. ant trail logs fetches a tail snapshot from the machine (--tail N, all); -f is local-only. Compose projects build each build: service on the machine and run the rest from images. run: stack deploys the raw stack file on a Swarm manager, routes domains at each service's published port, and maps zero_downtime to a Swarm start-first rolling update; its services need pullable images (build: is refused). Stack tasks carry ant's managed/app labels, so they appear in ant nest containers list and ant trail status, and ant trail logs <deployment> [service] reads one task's logs (name the service when the stack has several).

ant trail destroy --machine M stops and removes the deployment's workload on the machine and clears its Caddy routes; the machine's images are left in place.

Running this from a CI pipeline? See CI for a ci-role setup and ready-made GitHub Actions/GitLab jobs.

ant trail history reads the deploy log shared by the CLI and the dashboard. ant trail rollback redeploys a previously released image without rebuilding (the previous release by default, or --to RELEASE / --steps N), running the optional rollback.pre_hook / rollback.post_hook. It records a rollback entry (which does not shift the deploy sequence) and refuses compose and stack projects, their release is several images (compose) or a file that names them (stack), so redeploy those with an explicit --release or a pinned image. The release's image tag must still exist on the target, which deploy.keep_images / rollback.keep_releases control.

ant nest, machines, tools, scaffolding

Bare ant nest reports this machine's host facts, live usage, containers, and disk (--json for machine-readable output). Its subcommands are grouped by pillar:

  • Project: init, new, edit, templates
  • Groups: groups
  • Machine: machines, identity, tools, swarm, bootstrap, reconcile, doctor, ping, tunnel, audit, state, containers, volume
ant nest init                     [--port N] [--build X] [--run X] [--file F] [--target-machine M]
ant nest new                      TEMPLATE [DIR] [--app A] [--var K=V]... [--group G] [--target-machine M]
ant nest templates                list | search [QUERY] | show TEMPLATE [--json] | add ID | sync
ant nest edit                     file | env | secret | domain | deploy | deployment | volume | network | group
ant nest machines                 list | add NAME [--host H --ssh…] | remove NAME | decommission NAME --host H [--purge] [--handover] --yes | network M
ant nest identity                 show | generate [--force]
ant nest swarm                    status | init [--advertise-addr A] | leave [--force]
ant nest tools                    [--json] | install [tool...] [--dry-run] [--yes] | allow-ports [tool...] [--yes]
ant nest tools TOOL               status [--json]
                                  # TOOL: docker, caddy, nixpacks, pack, railpack
ant nest tools caddy              status [--json] | restart | stop
ant nest bootstrap                [--machine M] [--docker-mode MODE] [--host H --ssh… | --cloud-init --worker-url URL]
ant nest reconcile                [--apply --state F --yes]
ant nest doctor                   [--machine M] [--cleanup]
ant nest ping                     [machine] [--timeout 20s]
ant nest tunnel                   --machine M --container NAME --port P [--local L]
ant nest audit                    [--limit N] [--json]
ant nest state                    export [--out F] | import [--file F] [--force]
ant nest containers               list [--json] | start NAME | stop NAME | restart NAME | rm NAME --yes
ant nest volume                   list [--json] [--all] | rm NAME [--force] [--all] [--yes]
ant nest groups                   list | create | domains | network | add | remove | rename | delete

Flags by command:

CommandFlags
init--app, --build, --run, --file, --port, --group, --target-machine, --output, --force
new TEMPLATE [DIR]--app, --var KEY=VALUE (repeatable), --group, --target-machine, --force, --json
templates list--json
templates search [QUERY]--tag T (repeatable), --refresh, --limit N (default 25), --json
templates show TEMPLATE--json
templates add ID-
templates sync--repo URL, --ref R (default canary), --dir D
machines add NAME--id, --hostname, --node-id, --host, --ssh-user, --ssh-port, --ssh-key, --ssh-password/--ssh-password-stdin, --worker-bin, --docker-mode, --no-caddy, --no-caddy-check
machines decommission NAME--host, --ssh-*, --purge, --handover, --keep-record, --keep-identity, --yes
machines network MACHINE--name, --driver, --subnet, --external, --clear
identity generate--force
tools install--dry-run, --yes
tools allow-ports--yes
tools <tool> status--json
tools caddy restart / stop-
bootstrap--docker-mode, --host, --ssh-user, --ssh-port, --ssh-key, --ssh-password/--ssh-password-stdin, --worker-bin, --cloud-init, --worker-url (required with --cloud-init), --no-caddy
ping [machine]--timeout (default 20s)
tunnel--container (required), --port (required), --local
audit--limit N (default 50), --json
state export--out F
state import--file F, --force

ant nest tools is the tool surface (ant forage was retired).

Project templates

ant nest new TEMPLATE [DIR] creates a project from the catalog: it renders the template's files, writes generated secrets to .env (0600, gitignored), writes kind: database for database templates, and registers the project for discovery. Without DIR it uses ~/.ant-apps/<app> (/etc/ant/apps/<app> as root; override with ANT_APPS_DIR). --var KEY=VALUE sets a template variable, shown by ant nest templates show. The catalog is the Dokploy blueprints imported by ant nest templates sync; ~/.ant/templates/<id> overrides an imported template with the same id. See Templates.

ant nest identity manages a machine's iroh NodeID (the key it is dialed by). ant trail deploy --image is the low-level form for running one image on a machine; for a project-driven deploy that builds first, use ant trail deploy with machine: set in ant.yaml.

ant nest tunnel forwards a local TCP port to a container port on a machine over iroh, so a loopback-bound service can be reached with no inbound port on either side. The worker only reaches ports ant published on the machine's loopback for a container it manages, see Tunnels for the direction, the dashboard's equivalent, and troubleshooting.

ant nest audit shows the machine's tamper-evident action log: every privileged RPC (deploy, route, roster, volume, tunnel) is recorded with a hash chain, so a removed or edited line fails verification. The log rotates at 8 MiB and reading it requires the admin role.

ant nest state export|import backs up and restores a machine's daemon state (the roster and invites). Import is owner-only, refuses a document with no users unless --force is given, and keeps the previous file as agent-state.json.bak.

machines

ant nest machines add registers a nest. A machine is dialed by NodeID, so if you only have an address, provision it over SSH in one step:

ant nest machines add prod --host 173.87.3.89 --ssh-key ~/.ssh/id_ed25519
ant nest machines add prod --host 173.87.3.89 --ssh-password-stdin
ant nest machines add prod --hostname prod.example.com --node-id 7f2e…
ant nest machines network prod --name ant-prod --driver bridge

ant nest doctor checks the active machine; locally, or over the worker RPCs with --machine (host-level port grants are reported as not applicable remotely). It reports the docker daemon, Caddy reachability, the docker mode, and tool status. --cleanup also removes leftovers: on this host the pre-v2 config backup, world-readable deploy logs, and empty ~/.ant/local trees; on a machine the stored compose/stack projects whose workload is gone.

Provisioning needs a signed-in account (ant colony signup): its NodeID seeds the daemon's first owner, and ant ships the machine identity it generates. The docker compose and buildx plugins are installed when the distro ships them separately. The worker binary is pushed over SSH when provisioning that way (build it with task build:agent for the machine's architecture); --cloud-init instead downloads the published ant-worker-linux-<arch> release asset. When the SSH user is not root, the bootstrap runs through sudo; a passwordless sudo is used when available, and otherwise the SSH password (from --ssh-password / --ssh-password-stdin) is fed to sudo -S; the password never appears in argv or the environment. Flags: --id, --hostname, --node-id, --ssh-user, --ssh-port, --ssh-key, --ssh-password / --ssh-password-stdin, --docker-mode, --no-caddy, --no-caddy-check. The host may embed the port (--host 203.0.113.7:2222); an explicit --ssh-port wins over it.

ant nest machines remove only unregisters the machine locally. It deletes the local identity copy (~/.ant/machines/<id>) with the record; pass --keep-identity to keep the key for a later re-provision. To remove ant from the machine itself (stop and delete the worker, its unit, binary, and the Caddy admin drop-in, then unregister), use decommission over SSH:

ant nest machines decommission prod --host 173.87.3.89 --ssh-key ~/.ssh/id_ed25519 --yes
ant nest machines decommission prod --host 173.87.3.89 --ssh-password-stdin --purge --yes

--purge additionally removes the worker user and its state (the machine identity and roster), every ant-managed container and image, and the docker networks ant created for it. Without --purge the machine keeps /home/ant, so re-provisioning reuses the same NodeID and roster. --keep-record leaves the local entry in place.

swarm

ant nest swarm status --machine prod
ant nest swarm init --machine prod [--advertise-addr A]
ant nest swarm leave --machine prod --force
ant nest swarm nodes --machine prod
ant nest swarm node promote|demote|drain|activate|pause NODE --machine prod
ant nest swarm node rm NODE [--force] [--yes] --machine prod
ant nest swarm join-token [worker|manager] [--rotate] --machine prod
ant nest swarm services --machine prod
ant nest swarm service ps SERVICE --machine prod
ant nest swarm service logs SERVICE [--tail N] --machine prod
ant nest swarm service scale SERVICE REPLICAS --machine prod
ant nest swarm service restart SERVICE --machine prod
ant nest swarm service update SERVICE [--image REF] [--force] [--rollback] [--with-registry-auth] --machine prod
ant nest swarm service rm SERVICE [--yes] --machine prod

Swarm is a server feature: every subcommand requires a remote machine (--machine or ANT_MACHINE), and ant never initializes a swarm on this host. init makes the machine a single-node manager (--advertise-addr is only needed when docker cannot choose among its addresses); leave needs --force on a manager that still runs services.

Reads (status, nodes, services, service ps, service logs) need the read capability; node operations (init, leave, node …, join-token) need an admin or owner role on the machine; service mutations (service scale|restart|update|rm) need deploy. service update is for hotfixes; for lasting changes edit the stack file and redeploy, which is the zero-downtime path. service logs aggregates every replica's output, while ant trail logs reads one task. Anything beyond these commands (overlay/network admin, swarm configs and secrets, the rest of docker service update) stays docker on the machine.

bootstrap

ant nest bootstrap --machine prod                       # print the root plan
ant nest bootstrap --machine prod --host 173.87.3.89 --ssh-key ~/.ssh/id_ed25519
ant nest bootstrap --machine prod --cloud-init --worker-url https://host/ant-worker-linux-amd64
ant nest bootstrap --machine prod --host 173.87.3.89 --worker-bin ./bin/ant-worker

With --host, ant runs the plan over SSH, uploading the local ant-worker (default: next to ant, ./bin/ant-worker, $PATH, or ANT_WORKER_BIN; override with --worker-bin) and the machine identity; re-running it is also the upgrade path, and preserves the machine identity and roster. The docker mode is the recorded one unless --docker-mode is given, which re-provisions into that mode and updates the registry. It refuses a worker that is not a Linux ELF matching the target's architecture (uname -m). --cloud-init prints a user-data script that installs the worker from --worker-url (required, because the target must fetch the binary directly; use the ant-worker-linux-<arch> URL from the release's download directory) and reports its NodeID when you cannot SSH. With neither, it prints the steps for an operator to run as root.

Caddy's admin API

Ant programs routes through the machine's Caddy. The upstream packages expose that API on a root-only unix socket whose permissions vary across restarts, so the bootstrap points it at 127.0.0.1:2019 instead; it rewrites only the admin directive in /etc/caddy/Caddyfile (backup kept at /etc/caddy/Caddyfile.ant.bak) and restarts Caddy. A host already serving TCP on 127.0.0.1:2019 is left alone. If the Caddyfile cannot be adjusted, it falls back to the unix socket with a systemd drop-in that grants the worker access.

The worker starts even when Caddy is unreachable (it logs a warning and serves management, builds, and logs); deploys are refused with a clear message until Caddy answers again.

Tool status and service lifecycle

Every tool ant nest tools knows exposes status:

ant nest tools nixpacks status  # installed, version, path, install hint
ant nest tools docker status    # also reports whether the daemon answers

status reports whether the binary is on PATH, its version, path, and install hint. For Docker it also reports the daemon: status is ok only when docker info answers, so a stopped daemon shows as daemon unreachable, not as "not installed".

Only the one tool ant runs as a service (the local Caddy proxy) also exposes restart and stop:

ant nest tools caddy status     # listeners, routes, and a drift warning
ant nest tools caddy restart    # stop + start, applying a changed listen config
ant nest tools caddy stop       # stop it (domains go offline)

The other tools have no lifecycle to manage, so the verbs are not offered: nixpacks, pack, and railpack are one-shot build CLIs (they run, produce an image, and exit), and Docker's daemon is a host service ant does not own: restarting it stops every container and needs root, so ant nest tools install only prints the systemctl enable --now docker hint.

The local managed Caddy (which serves *.localhost domains) is the one service today. Its status reports the configured http_listen/https_listen, the programmed routes, and warns when the running proxy listens on different addresses than ~/.ant/config.json now asks for. A listen change does not reach a running proxy by itself: the next local deploy restarts it automatically, or run ant nest tools caddy restart to apply it immediately. A restart clears the programmed routes until the next deploy re-applies them. Both restart and stop work on the proxy whether or not ant still holds its PID file (they fall back to Caddy's admin API).

railpack additionally needs a BuildKit daemon. Provisioning starts one (docker run --name buildkit --privileged moby/buildkit) when railpack is already installed, and points the worker at it with BUILDKIT_HOST=docker-container://buildkit; install railpack first and re-run ant nest bootstrap to enable it.

edit

ant nest edit changes this project's ant.yaml in place, with comments preserved, the same edits the dashboard dialogs make.

CommandFlags
edit file- (opens ant.yaml in $VISUAL/$EDITOR and re-validates it)
edit deploy--build, --run, --dockerfile, --file, --files, --port, --cpu, --memory, --health-path, --health-interval, --health-timeout, --health-retries, --zero-downtime, --replicas, --log-max-size, --log-max-files, --keep-images, --profile (repeatable), --group-network, --machine-network, --build-services, --env
edit env list/set/unset--env (deployment; default local; list defaults to all)
edit secret add/list/removeadd --build-time, --env; remove --env
edit domain add/remove/listadd --subdomain --domain --path --group-domain --service --port --scheme --strip-slash --env; remove DOMAIN --env
edit deployment add/list/set/removeadd --compose-file --port-offset --auto-open; set --port-offset --auto-open
edit volume add/list/removeadd SOURCE:TARGET[:ro] [--source --target --read-only --target-machine]; remove TARGET [--target-machine]
edit network add/list/removeadd NAME [--driver --subnet --external]
edit group set/unset-

Notable deploy-level flags:

ant nest edit file                              # open the whole ant.yaml
ant nest edit deploy --replicas 2 --cpu 0.5 --memory 512m
ant nest edit deploy --machine-network          # join the machine-wide network
ant nest edit deploy --machine-network=false     # opt out
ant nest edit deploy --group-network=false       # opt out of the group network
ant nest edit deploy --env dev --file docker-compose.dev.yml
ant nest edit deploy --profile worker            # activate a compose profile

edit file is the escape hatch for anything the structured subcommands do not cover: it opens ant.yaml in $VISUAL/$EDITOR (falling back to nvim/vim/vi/nano) and re-reads it when the editor exits, so a syntax or config error is reported immediately. The edit is kept as written, so it can be fixed in place and the command re-run.

domain

ant nest edit domain add|remove|list manages ONE deployment's routes (--env, default local). Each entry carries its routing target: --service

  • --port for a compose service, or just --port (defaults to deploy.port for a single-container project). Domains are opt-in: ant never adds one. Omit --domain to use the project's group base domains; add --group-domain to pin one of them.
ant nest edit domain add --subdomain api --service web --port 3000
ant nest edit domain add --subdomain eu --group-domain example.org --service api --port 8080
ant nest edit domain add --path /internal
ant nest edit domain add api.other.org --service api --port 8080
ant nest edit domain list
ant nest edit domain remove api.localhost

deployment

ant nest edit deployment add|set|remove|list manages the per-environment overlays (local, dev, …). --compose-file sets that environment's compose file; --port-offset shifts its host port so two local deployments do not collide; --auto-open opens the browser after a local deploy.

volume

ant nest volume list               # name, driver, owner project, in-use
ant nest volume list --json
ant nest volume list --all         # include volumes no ant container uses
ant nest volume rm NAME --yes
ant nest volume rm NAME --yes --force
ant nest volume rm other-data --yes --all
ant nest volume list --machine prod

--force overrides a stopped container's reference; a running container still blocks removal. Pass --machine M to operate on a remote nest's volumes (the same list the dashboard shows on a machine's page).

To edit the project's own container mounts, use ant nest edit volume add|remove|list (short syntax SOURCE:TARGET[:ro], or --source/--target/ --read-only; --target-machine scopes a mount to one nest).

containers

ant nest containers list                     # name, status, image, CPU, memory
ant nest containers list --json
ant nest containers restart NAME
ant nest containers rm NAME --yes
ant nest containers list --machine prod

Lists and controls the ant-managed containers on the active machine; --machine targets a remote nest's worker. This is also the container list for the local machine, which ant trail ps used to provide.

machines network

ant nest machines network local                              # show the effective network
ant nest machines network local --name ant-local --driver bridge
ant nest machines network local --subnet 172.30.0.0/16 --external
ant nest machines network local --clear                      # back to the default

Shows or sets the machine-wide network projects opt into with deploy.use_machine_network. ant nest groups network <group> does the same for a group's shared network (--name, --driver, --subnet, --external, --no-attach, --clear).

groups

A group's base domains are what member deployments route under; a deployment adds a subdomain, a path, or uses one as-is. Add several bases with repeated --domain.

ant nest groups list
ant nest groups create backend --domain example.com --domain example.org
ant nest groups domains backend example.com example.org
ant nest groups add backend api worker
ant nest groups remove worker
ant nest groups rename backend services
ant nest groups delete backend --yes

create also takes --display-name, --color, --description, and --target-machine (the nest the group belongs to). domains <group> [domain...] replaces the base domains; add --clear to remove them.

ant colony, account and users

ant colony signup | login | logout | whoami
ant colony profile --name "Ada" --email ada@example.com
ant colony export --out ant-account.json [--passphrase P | --no-passphrase]
ant colony import ant-account.json [--passphrase P]
ant colony users                  list | add | update | remove | system-user
ant colony invite                 --role deployer --machine prod
ant colony join                   --token ant_inv_… [--alias NAME]
ant colony invites                [--revoke NONCE]
ant colony election-status
ant colony elect-owner <nodeid>
ant colony recover                --add-owner <nodeid>

Flags: signup --name --email; login --bundle --identity --passphrase; whoami --json; export --out --passphrase --no-passphrase; import --passphrase; invite --role --email --ttl (default 72h); join --token --alias; invites --revoke; recover --add-owner; users list --json; users add <nodeid> --role --name --email; users update <nodeid> --role --name --email --system-user --no-system-user; users remove <nodeid> --purge; users system-user <nodeid> --op create|lock|unlock|delete. The users subcommands also take --mirror (read and write the local roster mirror without contacting the machine daemon).

ant colony export/import move your account as a passphrase-encrypted bundle (import is login --bundle). ant colony users update changes a member's role (--role), name, email, or linked unix account (--system-user NAME links, including an existing account; --no-system-user detaches). ant colony users system-user --op create|lock|unlock|delete prints the matching root-run command. ant colony profile edits your own account. ant colony recover --add-owner is the break-glass path back onto a machine you are locked out of.

A user reference (<nodeid> above) may be a full NodeID, an unambiguous prefix of one, or an unambiguous name/email. With no --machine, the local machine's single user (your account) is targeted, so its linked system account can be set there too.

ant nest groups, project groups

See groups above; groups live in the client config (~/.ant/config.json) and are referenced by the group: field in ant.yaml.

Project secrets and env

Secrets are referenced by name in ant.yaml and resolved from the environment at deploy time; env vars are per-deployment. Both are edited through ant nest edit and printed by ant trail:

ant nest edit secret add API_TOKEN
ant nest edit secret add NPM_TOKEN --build-time
ant nest edit env set LOG_LEVEL=debug --env staging
ant trail env                     [deployment]

ant ui

ant ui                            [--host 127.0.0.1] [--port 4000]      # serve the dashboard
ant ui run                        [--host H] [--port P]                # same, explicit form
ant ui passwd                     [--clear | --password-stdin]         # set the dashboard password
ant ui install                    [--host H] [--port P] [--force]
ant ui status                     [--json]
ant ui start | stop | restart | recreate
ant ui logs                       [-f] [--lines N]
ant ui uninstall

ant ui install sets up a background service (a systemd user unit on Linux, a launchd agent on macOS) that keeps the dashboard running; ant ui recreate reinstalls it after a host/port change. The dashboard is local-only by design; ant ui passwd sets the password required to bind it to a non-loopback address for your own access (and --clear removes it). See the Dashboard page.

Surface parity

Everyday machine operations are on both surfaces. A few are deliberately CLI-only or dashboard-only:

  • CLI-only: account export (signup/login/logout/profile are on both); colony join and colony recover; nest identity generate; nest ping; nest machines decommission; the root-run bootstrap printing and reconcile/doctor (the dashboard shows the plans and can provision over SSH); swarm management (nest swarm …); nest tunnel; trail env and trail doctor; tool install --dry-run and the generic nest tools allow-ports (the dashboard installs tools and offers Caddy's port grant); and ant ui …, which manages the dashboard's own service.
  • Dashboard-only: live Caddy route state and Caddy lifecycle; project_dirs and the raw config/file editors; theme, refresh, and notification settings; the filesystem picker and global search; async job history/streams; deploy-event detail; and reassigning a project's machine after init.

Exit codes

Ant exits non-zero when Docker is missing or its daemon is unreachable. Caddy and the optional builders are warnings only.

Copyright © 2026