> ## Documentation Index
> Fetch the complete documentation index at: https://grounds-docs-platform-architecture.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# grounds push

> Build with Gradle, upload to forge, deploy to a target.

`grounds push` is the command you'll run dozens of times a day. It's a thin wrapper over the [Gradle plugin](/build/gradle-plugin/setup): the CLI invokes `./gradlew groundsPush` with the right arguments and inherits its stdout.

## Synopsis

```text theme={null}
grounds push [--target=dev|staging] [--project <id>] [--local <id>[,<id>]] [--with-local]
grounds push retry <pushId>
grounds push list [--target T] [--status S] [--limit N]
```

## push

```bash theme={null}
grounds push --target=dev       # default
grounds push --target=staging
grounds push --local plugin-chat
grounds push --local plugin-chat,plugin-permissions
grounds push --with-local
```

Runs `./gradlew groundsPush --target=<t>` in the current directory. The Gradle plugin handles:

* Resolving the JAR (auto-detects `shadowJar` or `jar`).
* Reading and validating `grounds.yaml`.
* Uploading JAR + manifest to forge.
* Streaming build + deploy logs back to your terminal.
* Exiting with a non-zero code on any terminal failure.

The CLI exits with the same code Gradle exits with.

By default, `grounds push` uses the release sources declared in
`grounds.yaml`. Local plugin builds are opt-in through
[workspace overrides](/build/cli/workspace).

### Local plugin overrides

Use `--local` when one or more entries in `grounds.yaml: plugins` should come
from your local workspace instead of the release source:

```bash theme={null}
grounds push --target=dev --local plugin-agones
grounds push --target=dev --local plugin-agones,plugin-player
grounds push --target=dev --local plugin-agones --local plugin-player
```

`--local` accepts both comma-separated IDs and repeated flags. IDs must match
the structured plugin `id` in `grounds.yaml`.

Use `--with-local` when every enabled workspace mapping present in
`grounds.yaml` should be replaced by its local artifact:

```bash theme={null}
grounds push --target=dev --with-local
```

Before Gradle runs, the CLI prints the effective source table:

```text theme={null}
Bundle sources:
ID              Variant   Effective   Value
plugin-agones   velocity  local       /home/alice/grounds/plugin-agones/velocity/build/libs/plugin-agones-velocity.jar
plugin-player   velocity  release     github:groundsgg/plugin-player@v0.1.0
```

The table is the confirmation step. It shows which plugins use local artifacts
and which still use release sources.

## push retry

```bash theme={null}
grounds push retry <pushId>
```

Re-runs the pipeline for a previously failed push. Forge re-uses the server-stored JAR and manifest, so this doesn't re-upload — it goes straight from `pending` to `building`. Use it when:

* A build failed because of a transient infra issue (image pull, registry hiccup).
* A deploy failed and you want to try again without rebuilding.

The retry creates a **new** push row with its own ID; the original is preserved for history.

## push list

```bash theme={null}
grounds push list                          # last 20 in current project
grounds push list --target=staging
grounds push list --status=ready
grounds push list --limit=50
grounds push list --output=json | jq .
```

| Flag       | Purpose                                                                                                           |
| ---------- | ----------------------------------------------------------------------------------------------------------------- |
| `--target` | Filter by target: `dev`, `staging`, `production`.                                                                 |
| `--status` | Filter by state: `pending`, `building`, `build_failed`, `build_succeeded`, `deploying`, `deploy_failed`, `ready`. |
| `--limit`  | Max rows to fetch (default 20, server cap 200).                                                                   |
| `--output` | `table` (default), `json`, or `yaml`.                                                                             |

## Common flags

These are all global flags and apply to every subcommand:

| Flag               | Env                  | Purpose                       |
| ------------------ | -------------------- | ----------------------------- |
| `--project <id>`   | `GROUNDS_PROJECT`    | Pin the project for this call |
| `--api-url <url>`  | `GROUNDS_API_URL`    | Override the forge endpoint   |
| `--config <dir>`   | `GROUNDS_CONFIG_DIR` | Override config dir           |
| `--output <fmt>`   | —                    | `table` / `json` / `yaml`     |
| `--verbose` / `-v` | —                    | Debug logs to stderr          |
| `--no-color`       | `NO_COLOR=1`         | Disable ANSI colors           |

## Reading the output

A successful push looks like:

```
→ uploading my-cool-plugin-0.1.0.jar (4.2 MB)
✔ uploaded — pushId=018f9c12-…
[build] step 1/5 …
[build] step 5/5 done
✔ build_succeeded — image registry.platform.grnds.io/my-cool-plugin@sha256:…
[deploy] reconciling deployment my-cool-plugin in user-hendrik
[deploy] pod scheduled
[deploy] pod ready
✔ ready — connect at my-cool-plugin-hendrik.mc.grnds.io
```

If the pod ends up `CrashLoopBackOff`, you'll see deploy logs streamed before the CLI gives up and prints `deploy_failed`. Tail the live deployment logs separately at any time:

```bash theme={null}
grounds logs deployment my-cool-plugin
```

## Exit codes

For a practical failure investigation flow, see
[Debug pushes and deployments](/build/debug-pushes).

| Code | Meaning                                       |
| ---- | --------------------------------------------- |
| 0    | `ready` reached                               |
| 1    | Generic failure (validation, network, config) |
| 2    | `build_failed`                                |
| 3    | `deploy_failed`                               |
| 130  | Cancelled by user (Ctrl-C)                    |

Anything non-zero is safe to fail a CI step on.
