# Deploy an app with Nubes

Nubes is a hosting platform at https://usenubes.com. Documentation: https://docs.usenubes.com. Dashboard: https://app.usenubes.com.

## Identify the project first

Before installing tools, opening login, building, or deploying, inspect the current working directory. If it is not an application project, or more than one app could be the target, stop immediately and ask the user which directory to deploy. Do not select a nearby repository or deploy an example in its place.

Identify the runtime, package manager, build command, output directory, environment variables, and intended production or staging target. Read existing AGENTS.md and nubes.hcl files and preserve user changes. Keep credentials out of configuration, prompts, logs, and source archives.

## Install and sign in

The native CLI supports macOS and Linux on amd64 and arm64. Windows users can use WSL.

```sh
curl --fail --silent --show-error --location https://usenubes.com/setup.sh -o /tmp/nubes-setup.sh
sh /tmp/nubes-setup.sh
export PATH="$HOME/.local/bin:$PATH"
export NUBES_API_URL='https://fast-greyhound-109.convex.site'
nubes login
```

The installer verifies the downloaded archive's SHA-256 checksum and extracts the native binary. It requires curl, tar with xz support, and sha256sum or shasum. A source build is also possible from the Nubes repository using Go; do not use an unofficial npm package named Nubes.

Login opens a WorkOS verification page and prints a confirmation code. Bring that browser tab to the foreground when browser controls are available. Let the user sign in and approve the code. Do not enter their password, accept consent on their behalf, or request their access token. In a headless terminal use `nubes login --no-browser` and show the verification link.

If login reports missing WorkOS CLI configuration, report the exact error and stop authentication. The service operator must configure a public WorkOS Connect application with device authorization, `WORKOS_CLI_CLIENT_ID`, `WORKOS_AUTHKIT_DOMAIN`, and `MCP_RESOURCE_URL`.

Verify the session with `nubes api auth.get --json`. The CLI keeps its session in the operating system's user configuration directory and refreshes it when needed. `NUBES_TOKEN` remains available for service and CI API keys and takes precedence over the saved login.

## Choose the deployment path

Read https://docs.usenubes.com/apps and https://docs.usenubes.com/sites before generating infrastructure. The CLI supports Node.js, Bun 1.4, PHP, Go, Rust, Java, Ruby, C#, Elixir, Swift, OCaml, and Python server apps, plus static directory output. Use source labels `nodejs`, `bun`, `php`, `go`, `rust`, `java`, `ruby`, `csharp`, `elixir`, `swift`, `ocaml`, or `python`. `package_manager` applies only to Node.js. Optional `build` and `start` commands run inside the selected Linux language environment. Server apps must listen on `0.0.0.0` and use the `PORT` environment variable. Static sites may use `routing = "spa"` for client-side routing.

Container-image and Dockerfile sources are not supported by the current CLI or deployment API. For a container-only project, explain this limitation and ask how the user wants to proceed. Do not silently convert it into a different runtime or invent container configuration.

Use `version = 1` and the resource blocks the project needs. Example server:

```hcl
version = 1
app "web" {
  source "nodejs" {
    path = "."
    package_manager = "pnpm"
    build = "pnpm build"
    start = "pnpm start"
  }
}
```

Example static site:

```hcl
version = 1
site "web" {
  source "directory" { path = "./dist" }
  builder = "pnpm build"
  routing = "spa"
}
```

Adjust commands to the actual application. Use symbolic secret references, never secret values. Do not add HCL output blocks. Run `nubes validate nubes.hcl`, `nubes build nubes.hcl`, then `nubes plan nubes.hcl --json`.

## Select the workspace and deploy

Use `nubes api --json` to discover API operations (a JSON array keyed by `operationId`) and `nubes api <operation> --describe --json` to inspect required inputs. If `NUBES_PROJECT_ID` is already selected, verify it directly with `project.get` and a `projectId` parameter; do not call team discovery unnecessarily. `auth.get` returns the WorkOS organization; `project.list` requires the Nubes team ID. For a signed-in user, `dashboard.home` discovers their accessible team and project IDs. Ask the user only when the intended target remains ambiguous; never guess an ID. Set `NUBES_PROJECT_ID` or pass `--project-id`.

Show the planned resources and target. A user's clear instruction to deploy authorizes this deployment; ask only if the target or scope remains ambiguous. Deployment requires spendable credit unless the workspace has explicitly enabled free-unlimited billing. If credit is insufficient, direct the user to the dashboard billing page to top up, then retry after they complete checkout.

```sh
nubes deploy nubes.hcl --environment production --json
```

Wait for terminal success. Before each unfamiliar API call, use `--describe --json` and follow its parameter and body schemas rather than guessing fields. Inspect `deployment.get` and `deployment.history`; both require `deploymentId`. For static sites, obtain the URL with `site.list`, which requires `projectId`.

Fetch the actual deployed URL using an HTTP client such as curl. Check its HTTP status and response body against the expected application content. A hostname by itself is not a content check. Route propagation can take up to 30 seconds; retry within that window if needed. If verification still fails, report the failure and investigate rather than declaring success. Report the deployment ID and verified public URL only after both deployment and content checks pass. An accepted request or successful upload is not a completed deployment.

## MCP

Use the remote MCP endpoint at https://fast-greyhound-109.convex.site/mcp with WorkOS OAuth. It publishes OAuth discovery metadata and a `whoami` tool. Generic clients use the advertised standard OpenID scopes. Approving a connection grants access to the selected organization subject to your current Nubes membership role. Discover the current tool list; API operations are also exposed as MCP tools. Generated API tools accept path/query fields in `parameters` and JSON request payloads in `body`. Private provider callbacks are not agent tools.

The liveness API is `GET /v1/health`. Public `GET /v1/health/platform` (CLI `system.platformHealth`) reports today’s measured Nubes platform availability from five-minute probes; missing or stale measurements are `unknown`. Authenticated `GET /v1/health/daily` (CLI `system.dailyHealth`) reports the current UTC day's deployment summary for the selected organization, including whether bounded results are partial. It is a deployment summary, not a probe of every app's uptime.

Bun apps use `source "bun" { path = "./app" }`, pinned to Bun 1.4.2, with `bun install --frozen-lockfile` and `bun start` by default. Commit `bun.lock` alongside `package.json`. Existing Node.js sources with `package_manager = "bun"` also use the Bun image.
