| title | CLI |
|---|---|
| description | The swarmed command-line interface to SwarmMedHub, run inside the application container. |
swarmed is the command-line interface (CLI) to SwarmMedHub. It is part of the
same repository, calls the same Django services as the web interface, and uses
the same database records, object storage, Celery tasks and active
project/network context.
- In SwarmMed 1.0.0 the CLI runs on the SwarmMedHub host, inside the application container. It is not a client for a remote Hub.
- It has so far been run only on Linux hosts (Operating systems). From macOS or Windows, use it over SSH on the platform host.
- It covers the executable workflow: projects, data, networks, training and results. User management and the log viewer are only in the web interface.
- It performs no authentication. It acts as the user it is given (below), so anyone who can run commands in the application container can act as any user (Security).
On a SwarmMedHub host, run the CLI inside the application container
(swarmmedhub), where the repository is mounted at /app:
docker exec -w /app swarmmedhub python3 -m swarmed_cli.main --helpFrom the repository directory, docker compose exec app python3 -m swarmed_cli.main …
is equivalent. Call the module with python3 -m: the swarmed command installed
in the image cannot import the package from the mounted repository.
The examples on this page write swarmed for that command. To type them as
shown, define a shell function in your session:
swarmed() { docker exec -w /app swarmmedhub python3 -m swarmed_cli.main "$@"; }When the CLI runs in the container:
- Paths are resolved inside the container, whose working directory
/appis the repository directory.--code-dir, the files given todata import,--packageand--outmust therefore lie inside the repository directory on the host, for example./demo-codeortmp/startup.zip. - Environment variables for one command are passed with
docker exec -e, for exampledocker exec -e SWARMMEDHUB_SWARM_ROUNDS=2 -w /app swarmmedhub python3 -m swarmed_cli.main training start ….training startbuilds and submits the job in the CLI process, so such variables apply to it.network starthands the start to the Celery worker, so variables that control how a network starts, such as client-only mode, must be set for the worker (Networking). - Do not run
uvinside the container./appis the host's repository directory, and uv treats the host's.venvas broken there: it deletes it and creates an empty one owned by root.
The acting user resolves in this order:
--user USERNAMESWARMED_USER(pass it withdocker exec -e SWARMED_USER=<name> …)- the operating-system user name, which inside the container is
root
If no matching SwarmMedHub user exists, the command exits with a validation error.
make install also installs a swarmed command into the host's .venv
(uv run swarmed …). On a SwarmMedHub host it fails as installed: the generated
.env addresses the database as postgres and the object store as minio, and
Redis is addressed as redis by default; these names resolve only inside the
Docker network. Run on the host, the CLI needs at least:
DB_HOST=127.0.0.1, andDB_PORTset to the published database port (POSTGRES_HOST_PORT, 5432 by default);- the internal CA certificate where the database connection looks for it,
/usr/local/share/ca-certificates/internal-ca.crt, unlessDB_SSLROOTCERTorCA_CERT_PATHnames another path. WithDEBUG=Falsethe connection verifies the server's certificate (sslmode=verify-full).
Commands that use the object store, or that queue work for the Celery worker,
also need MinIO and Redis; no host-side configuration for them has been tested.
The worked example's training hosts ran the CLI this way, with
DB_HOST=127.0.0.1, on a reduced installation without the web application,
worker or object store, to import the startup package; each call stalled about
20 s retrying Redis (Reproducing the worked example).
Every command supports --json.
{
"ok": true,
"command": "project list",
"result": {},
"warnings": [],
"errors": []
}Exit codes:
0: success2: usage or validation error1: unexpected failure
network start --wait returns when the network is running or has failed, and
exits with code 2 if it ends in the ERROR state.
training.py is required at the root of --code-dir.
Optional root-level files are picked up automatically:
requirements.txtvalidation.pyvisualization.pyresults_visualization.py
Any other files under the directory are imported under the existing training code layout.
swarmed project create \
--user alice \
--title "Demo Project" \
--description "CLI workflow" \
--code-dir ./demo-codeswarmed project use --user alice <PROJECT_UUID>swarmed data import \
--user alice \
--project <PROJECT_UUID> \
--dest incoming \
./data/patients.csv ./data/imagesswarmed data validate --user alice --project <PROJECT_UUID>
swarmed data visualize --user alice --project <PROJECT_UUID> --waitLocal test network, with all participants on this host (--clients N sets the
number of clients, 2 by default):
swarmed network create \
--user alice \
--project <PROJECT_UUID> \
--name "Local Test" \
--local-testProvisioned startup-package network:
swarmed network create \
--user alice \
--project <PROJECT_UUID> \
--name "Hospital Swarm" \
--participant site-a=100.64.0.10 \
--participant site-b=100.64.0.11Each --participant NAME=IPv4 needs an IPv4 address that stays assigned to that
site's host for the study (Networking). Without
--server-ip, the FL server's address is this host's Tailscale address. Unless
--no-local-client is given, this host is also added as a training client, named
after its SWARMMEDHUB_HOSTNAME.
For server/admin-only hosts, prevent the local host from being added as an extra training client:
swarmed network create \
--user alice \
--project <PROJECT_UUID> \
--name "Hospital Swarm" \
--server-ip 100.64.0.1 \
--participant site-a=100.64.0.10 \
--participant site-b=100.64.0.11 \
--no-local-clientExport the startup package for the other sites:
swarmed network export-package --user alice <NETWORK_UUID> --out tmp/startup-kits.zip!!! warning "The startup package is the study's master credential"
The package contains every participant's private key, the FL server's
private key, and for each site an admin identity with NVFlare's
project_admin role, which may run code at every site. Write it to a path
that git ignores, such as tmp/, move it only over an encrypted,
authenticated channel, and delete copies once they are imported (see
Key custody).
Without --out, the package is written to the repository directory as
<network name>_startup_kits.zip.
Import an existing startup package:
swarmed network import \
--user alice \
--project <PROJECT_UUID> \
--name "Imported Network" \
--package tmp/startup-kits.zipswarmed network use --user alice <NETWORK_UUID>
swarmed network start --user alice <NETWORK_UUID> --waitAt a participating site, set client-only mode for the worker before starting the network; otherwise the start also launches a copy of the FL server from the imported package. A coordinating host that does not train uses server-only mode. Both are described in Networking.
swarmed training start --user alice --network <NETWORK_UUID>
swarmed training watch --user alice <JOB_UUID>The network must be running on this Hub. The job is not submitted if the
project's stored code has no training.py, for example while the object store is
unavailable. The number of rounds comes from SWARMMEDHUB_SWARM_ROUNDS, passed
with docker exec -e, or else from SWARM_ROUNDS in training.py, and is 10 if
neither is set (Developer).
swarmed results sync --user alice --project <PROJECT_UUID>
swarmed results list --user alice --project <PROJECT_UUID>
swarmed results export \
--user alice \
--project <PROJECT_UUID> \
--job <JOB_UUID> \
--out ./resultsswarmed results visualize \
--user alice \
--project <PROJECT_UUID> \
--job <JOB_UUID> \
--waitproject create|list|show|use|update
data import|ls|export|mv|rm|validate|visualize
network create|import|list|show|use|export-package|start|stop|status
training start|list|status|watch|stop
results sync|list|export|visualize