---
name: hubfly-cli
description: Deploy and operate applications on Hubfly space with the Hubfly space CLI. Use for Hubfly space build manifests, deployment planning and reconciliation, single-app or Compose deployments, deployment sessions, logs, tunnels, SSH, exec, projects, authentication, updates, or troubleshooting.
---

# Hubfly space CLI

Use `hubfly` as the client of the Hubfly space Dashboard control plane. The CLI builds images locally, uploads them to the selected region, and follows the asynchronous Dashboard deployment session through its real terminal state. Inspect first, preserve secrets, obtain approval immediately before consequential actions, and report the phase that actually completed.

## Orient to the application

1. Confirm the working directory and requested outcome.
2. Inspect `hubfly.build.json`, Dockerfiles, Compose files, build/run commands, ports, healthchecks, volumes, resource settings, and environment-variable names. Do not print secret values.
3. Check the client and identity with `hubfly version` and `hubfly whoami`.
4. If the CLI is absent, propose the official installer and obtain approval before running it:

   ```bash
   curl -fsSL https://raw.githubusercontent.com/hubfly-space/hubfly-cli/main/install.sh | bash
   ```

5. If authentication is required, ask the user to run `hubfly login`, or use `HUBFLY_TOKEN` from their secure environment. Never put a token in a command shown in logs, a tracked file, or skill output.

`hubfly.build.json` is the durable binding between a local application and its Hubfly space project/container. The current schema is version 2. Preserve its project and container IDs after successful deployments; do not treat it as disposable generated output.

## Select the workflow

- Single app or Dockerfile: `hubfly deploy`.
- Preview reconciliation without building/uploading: `hubfly deploy plan` (add `--json` for machine-readable output).
- Adopt the current bound container configuration locally: `hubfly deploy pull`.
- Compose application: `hubfly stack plan`, then `hubfly stack up`.
- Build/config inspection: `hubfly build validate` and `hubfly build explain`.
- Detached or interrupted deployment: `hubfly deploy status` and `hubfly deploy events`.
- Runtime diagnosis: `hubfly logs`, `hubfly stack logs`, or the grouped `hubfly container` commands.
- Private access: `hubfly tunnel`, `hubfly ssh`, or `hubfly exec`.
- Local daemon integration: `hubfly service`.
- Update check: `hubfly update --check`; install an update only with `hubfly update` after approval.

## Current command surface

```text
hubfly login [--token <TOKEN>]
hubfly logout
hubfly whoami
hubfly auth login|logout|status
hubfly projects [--org <id|slug>]
hubfly orgs
hubfly project list [--org <id|slug>]

hubfly deploy [advanced|plan|pull] [--advanced]
  [--project <id|name|new>] [--region <region>] [--org <id|slug>]
  [--config <path>] [--dockerfile <path>] [--builder-version <tag>]
  [--mode smart|replace] [--force-new] [--detach] [--json] [--yes]
hubfly deploy status|events|cancel|retry <buildId>

hubfly build init|validate|edit|explain
  [--config <path>] [--dockerfile <path>] [--builder-version <tag>]
  [--force] [--print] [--json]
hubfly build init
hubfly build validate --json
hubfly build edit
hubfly build explain --json
hubfly config validate|explain
hubfly config migrate [--config <path>]

hubfly stack plan|up|status|logs|exec|ssh|down [options]
hubfly stack plan --file <compose-file>
hubfly stack down [--volumes] [--yes]
hubfly compose plan|up|status|logs|exec|ssh|down [options]

hubfly logs <containerIdOrName> [--follow|-f]
hubfly tunnel <containerIdOrName> <localPort> <targetPort>
hubfly ssh <containerIdOrName> [-- <cmd> [args...]]
hubfly exec <containerIdOrName> -- <cmd> [args...]
hubfly container logs|tunnel|ssh|exec <container> ...

hubfly version
hubfly update [--check]
hubfly service [--port <port>]
```

Use `hubfly help` and the relevant command's current usage output when a flag is uncertain. Do not invent a command from Dashboard UI terminology.

## Understand the deployment model

A current single-app deployment has distinct phases:

1. The CLI loads or creates schema-v2 `hubfly.build.json`, applies requested overrides, and resolves the target project/region.
2. It downloads or reuses the selected `hubfly-builder`, inspects the source, and prepares a Dockerfile/build plan locally.
3. It compares the desired manifest with the bound cloud container and asks Dashboard for a server-side deployment plan. The plan includes revision guards and destructive operations.
4. After approval, Dashboard creates an authenticated deployment session and a short-lived regional registry upload credential.
5. The CLI builds locally, uploads the image, and signals upload completion. Dashboard owns deployment, health checks, reconciliation, and cutover.
6. Unless `--detach` was approved, the CLI follows the session until `success` or `failed`, then updates the local binding metadata.

An image build or upload is not a successful deployment. Dashboard is the system of record for the remote session; Hubcell owns regional runtime state behind it.

### Smart and replace reconciliation

Use `--mode smart` by default. Smart mode adopts cloud values for fields the local manifest does not manage and changes only explicitly managed fields.

Use `--mode replace` only when the user intends the local manifest to replace the remote configuration. Review removals of environment keys, ports, and volumes before approval. Never use replace merely to resolve drift.

For an existing bound container, `hubfly deploy pull` copies cloud configuration into the local manifest. It preserves local values for non-secret environment variables where possible and leaves cloud secret values blank. It can overwrite local configuration, so show the diff and obtain approval before writing, especially when the manifest has uncommitted changes.

### Planning and configuration writes

Prefer:

```bash
hubfly deploy plan --config <path> --mode smart --json
```

This avoids image build/upload and remote rollout, but it is not guaranteed to be filesystem- or account-read-only: the CLI may initialize/normalize `hubfly.build.json`, prepare `.hubfly/Dockerfile.generated`, download a builder, or bind/create a requested project. Inspect the workspace and target flags first; obtain approval if the preview would create or overwrite local files or remote project state.

`hubfly build validate` and `hubfly build explain` may also initialize or normalize configuration and prepare generated build artifacts. Do not promise a no-write validation unless current behavior has been checked in an isolated copy.

If the manifest is schema version 1, do not bypass the guard. Propose:

```bash
hubfly config migrate --config <path>
```

Migration creates a timestamped `.bak` file and rewrites the manifest as version 2, so it requires approval.

## Deploy safely

For a new or uncertain target, use the interactive flow:

```bash
hubfly deploy
```

For a fully specified, approved operation:

```bash
hubfly deploy --project <id|name|new> --region <region> \
  --config <path> --mode smart --yes
```

- `--project` selects an existing project or requests creation with `new`.
- `--region` is required for non-interactive creation when no usable binding exists.
- `--org` scopes project selection.
- `--dockerfile` forces a Dockerfile for this run.
- `--builder-version` pins inspection/build behavior for reproducibility.
- `--detach` returns after upload; retain the build ID and verify later with status/events.
- `--json` is especially useful with `deploy plan`.
- `--yes` suppresses CLI prompts; it never supplies user authorization.

The `--yes` flag is not user authorization. It only suppresses interactive CLI confirmation after the user approves the exact operation.

If another deployment is active for the bound container, the normal CLI attaches to that session rather than starting a competing rollout. Report that behavior. Use `--force-new` only when the user explicitly approves canceling the named active build and starting a replacement; non-interactive use also requires `--yes`.

## Compose stacks

Plan and review before applying:

```bash
hubfly stack plan --file <compose-file>
hubfly stack up --file <compose-file> --project <id|name|new> \
  --region <region> --yes
```

Compose services become ordinary Hubfly space containers and use the same Dashboard/session/runtime contracts. Check supported Compose fields and warnings rather than assuming full Docker Compose compatibility.

- Use `--no-build` only when existing images are intentional.
- Use `--remove-orphans` only after naming the managed services it may remove.
- Diagnose with `hubfly stack status` and `hubfly stack logs [service...] --follow`.
- Treat `hubfly stack down --volumes` as destructive data deletion and require a separate explicit confirmation naming the volumes.

## Approval boundary

Local source inspection, identity/version checks, existing status/events, log reads, and `update --check` are normally safe without confirmation.

Immediately before installing/updating the CLI, authenticating or revoking authentication, creating/binding a project, writing/migrating/pulling configuration, starting/canceling/retrying/superseding a deployment, applying a stack, opening remote access, executing a remote command, or tearing resources down:

1. Show the exact command.
2. Name the organization, project, region, container/services, build ID, and persistent resources affected when known.
3. Explain overwrites, removals, downtime, cost, and data-loss risk.
4. Obtain explicit approval for that operation.

Do not reuse approval for a materially different target or command. Stop retrying when the same remote failure repeats or a retry could duplicate/cancel work; inspect session status and events before proposing the next mutation.

## Diagnose deployment sessions

Use the build ID returned by the CLI:

```bash
hubfly deploy status <buildId>
hubfly deploy events <buildId>
```

Use `cancel` or `retry` only after approval:

```bash
hubfly deploy cancel <buildId>
hubfly deploy retry <buildId>
```

Differentiate configuration/planning, local builder inspection, local Docker build, regional upload, Dashboard reconciliation, runtime health/cutover, and final session failure. Include the CLI's backend trace ID and error code when present, while redacting credentials and private values.

For runtime access, use the narrowest approved command:

```bash
hubfly logs <containerIdOrName> --follow
hubfly tunnel <containerIdOrName> <localPort> <targetPort>
hubfly ssh <containerIdOrName>
hubfly exec <containerIdOrName> -- <cmd> [args...]
```

Avoid commands such as `printenv` when they could expose secrets. Quote only the relevant log lines and redact tokens, cookies, credentials, private keys, registry upload URLs, and secret environment values.

## Verify and report

1. Unless detachment was approved, wait for the deployment session's terminal state.
2. Report the project, container/services, region, build ID, apply mode, and final status.
3. Verify the requested behavior through a safe status or health endpoint when available.
4. If detached, state that upload completed but deployment remains asynchronous, and provide the exact status/events commands.
5. If blocked by approval, authentication, balance, permissions, network health, local Docker/build errors, or regional service health, name the exact phase and blocker.
6. Never infer zero downtime from the existence of a deployment endpoint. Report cutover/health evidence only when the Dashboard session or observed application behavior confirms it.

Never report success merely because an image built or uploaded; require the final Dashboard session result or clearly state that remote completion remains unverified.
