# Platform CLI (/docs/deployment/platform-cli)



The `bsqai-platform` CLI is the primary tool for generating and deploying BullSequana AI platform manifests. It reads TOML configuration and Jinja2 templates, produces Kubernetes manifests, seals secrets, and pushes the output to a Git repository for ArgoCD to reconcile.

Prerequisites [#prerequisites]

| Requirement       | Details                                                                                        |
| ----------------- | ---------------------------------------------------------------------------------------------- |
| Python            | 3.12                                                                                           |
| Package manager   | `uv`                                                                                           |
| `kubeseal`        | Required for secret sealing (must match the cluster's sealed-secrets version)                  |
| Kubernetes access | Kubeconfig at `<repo-root>/.kube/config` (not `~/.kube/config`)                                |
| Environment files | `platform.env` (shared) and optionally `local.env` (personal overrides) at the repository root |
| Git token         | `PERSONAL_GIT_TOKEN` env var for pushing manifests                                             |

Running the CLI [#running-the-cli]

All commands are invoked through `uv`:

```bash
uv run -m src.cli.main <command> [arguments] [options]
```

Commands [#commands]

test-k8s [#test-k8s]

Test connection to the Kubernetes cluster using the kubeconfig at `<repo-root>/.kube/config`.

```bash
uv run -m src.cli.main test-k8s
```

Exits with code `0` on success, `1` on failure. Use this to verify cluster connectivity before running any deployment commands.

list-components [#list-components]

List all components available in the current platform version.

```bash
uv run -m src.cli.main list-components
```

Components are discovered by scanning directories under `src/manifests/source/<group>/`. The output is sorted alphabetically.

validate [#validate]

Validate the structure of all component definitions.

```bash
uv run -m src.cli.main validate
```

For each component, validation checks:

* `variables.toml` exists
* the `format` field is one of `helm`, `kustomize`, or `yaml`
* required files are present (`values.yaml.j2` for Helm, `kustomization.yaml` for Kustomize)

load [#load]

Load and resolve all TOML variables for the specified component(s). Useful for inspecting resolved configuration without generating manifests.

```bash
uv run -m src.cli.main load                    # all components
uv run -m src.cli.main load keycloak             # specific component
```

Resolution applies environment variable overrides, generators, and global defaults. See [Configuration model](/docs/deployment/configuration-model) for the full resolution chain.

apply [#apply]

Generate output manifests for the specified component(s).

```bash
uv run -m src.cli.main apply all -r             # all components, replace existing output
uv run -m src.cli.main apply keycloak             # specific component only
```

| Option            | Description                                                                               |
| ----------------- | ----------------------------------------------------------------------------------------- |
| `-r`, `--replace` | Delete the existing output directory before generating. Default is `false` (incremental). |

This is the core command. For each component it:

1. Loads and resolves the global `platform.toml` and all component `variables.toml` files
2. Renders Jinja2 templates (`values.yaml.j2`, `resources/*.yaml.j2`, `secrets/*.yaml.j2`)
3. Seals any rendered `Secret` manifests with `kubeseal`
4. Generates an ArgoCD `Application` manifest for each component
5. Generates parent app-of-apps manifests for each group (`common`, `coreai`, `proai`)

Output is written to `src/manifests/output/`.

push-manifests [#push-manifests]

Commit and push the generated manifests to the Git repository.

```bash
uv run -m src.cli.main push-manifests "Release 1.2.0"
```

Requires three environment variables:

| Variable             | Purpose                  |
| -------------------- | ------------------------ |
| `GIT_REPO_URL`       | Manifests repository URL |
| `GIT_BRANCH`         | Target branch            |
| `PERSONAL_GIT_TOKEN` | Git authentication token |

The CLI clones the target repository, replaces its content with the generated output from `src/manifests/output/`, commits, and pushes.

apply-sealing-key [#apply-sealing-key]

Install the sealed-secrets keypair and registry pull secret on the Kubernetes cluster.

```bash
uv run -m src.cli.main apply-sealing-key                  # default namespace: sealed-secrets
uv run -m src.cli.main apply-sealing-key my-namespace      # custom namespace
```

This command touches the cluster directly. It applies:

* the sealed-secrets TLS keypair from `src/manifests/seal/`
* the container registry pull secret (from `COMMON_DOCKERCONFIGJSON` env var)

Run this once before the first deployment to bootstrap the sealing infrastructure.

helm-apply [#helm-apply]

Deploy a component directly via Helm (bypassing GitOps).

```bash
uv run -m src.cli.main helm-apply argocd
```

This is used exclusively for bootstrapping ArgoCD, the only component that cannot deploy itself through GitOps. The command:

1. Logs into the container registry
2. Loads and renders the component's `values.yaml.j2`
3. Runs `helm install` or `helm upgrade` against the cluster

Requires `COMMON_REGISTRY_NAME`, `COMMON_REGISTRY_AUTH_USERNAME`, and `COMMON_REGISTRY_AUTH_TOKEN` environment variables.

Debugging [#debugging]

Both `push-manifests` and `helm-apply` work in temporary locations — a cloned copy of the manifests repository and a rendered Helm values file respectively — that are deleted when the command finishes.

Set `CLEANUP_TEMPORARY_FILES=false` (platform 1.2.1 and later) to keep them after the run for inspection. Any other value, or leaving the variable unset, keeps the default cleanup behavior.

Typical deployment sequence [#typical-deployment-sequence]

Initial deployment [#initial-deployment]

```bash
# 1. Verify cluster connectivity
uv run -m src.cli.main test-k8s

# 2. Generate all manifests
uv run -m src.cli.main apply all

# 3. Push to the manifests repository
uv run -m src.cli.main push-manifests "Initial deployment"

# 4. Install the sealing key
uv run -m src.cli.main apply-sealing-key

# 5. Bootstrap ArgoCD
uv run -m src.cli.main helm-apply argocd
```

After step 5, ArgoCD reconciles the manifests from Git and deploys all components to the cluster.

Subsequent configuration changes [#subsequent-configuration-changes]

```bash
# 1. Regenerate all manifests (replace mode wipes the output directory to avoid stale configuration)
uv run -m src.cli.main apply all -r

# 2. Push to the manifests repository
uv run -m src.cli.main push-manifests "Description of changes"
```

ArgoCD detects the Git changes and reconciles automatically.

Related pages [#related-pages]

* [Configuration model](/docs/deployment/configuration-model)
* [GitOps workflow](/docs/deployment/gitops-workflow)
* [Component anatomy](/docs/deployment/component-anatomy)
* [Deployment sequence](/docs/deployment/playbooks/deployment-sequence)
