> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wp-content.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrading to v2

> What changed between wpc 1.x and 2.0, and what to check in your scripts

`wpc` v2 renames its commands. What used to be `wpc plugin:ls` is now
`wpc plugin list` — one word for the thing, one word for what you do to it, the
shape you already know from `docker`, `git` and `gh`.

**The command names you have written keep working.** Every v1 name is a
permanent alias, and so is `--paged`. A pipeline pulling the `latest` Docker
image moves to v2 without anyone typing a command, so renaming things must not
break it.

v2 does change how failures are reported and how JSON answers are shaped. If a
script reads exit codes or parses `--output=json`, read
[what changed for scripts](#what-changed-for-scripts) before you upgrade.

## The new names

| v1 | v2 |
| - | - |
| `wpc plugin:start` | `wpc plugin init` |
| `wpc plugin:manifest` | `wpc plugin manifest` |
| `wpc plugin:build` | `wpc plugin build` |
| `wpc plugin:push` | `wpc plugin push` |
| `wpc plugin:ls` | `wpc plugin list` |
| `wpc plugin:info` | `wpc plugin info` |

The `theme:*` commands follow the same pattern. The list option `--paged` is
now `--page`; `--paged` keeps working.

`ls` and `start` survive as aliases of the new names too, so `wpc plugin ls`
does what you would expect.

## What you will see

Run an old name, or `--paged`, and `wpc` prints one line on **standard error**:

```
wpc: "plugin:ls" is deprecated, use "wpc plugin list". The old name will keep working.
```

It goes to standard error on purpose: `wpc plugin:ls --output=json | jq` keeps
working untouched, and the notice still shows up in your CI log — which is the
only place it can reach whoever maintains the pipeline.

It is silenced by `--output=json`, by `-q/--quiet`, and by an environment
variable if you would rather deal with it later:

```bash theme={null}
export WPC_NO_DEPRECATED_WARNING=1
```

<Note>
  We do not plan to remove the old names. The notice exists so new
  documentation, new scripts and new colleagues converge on one spelling — not
  as a countdown.
</Note>

## What changed for scripts

### Exit codes

Every command now uses the same three codes:

| Code | Meaning |
| - | - |
| `0` | Success. |
| `2` | The command was called wrongly: unknown command or option, missing argument, invalid `--output`, file or directory not found, invalid `--slug` or `--filename`, missing repository or API key. |
| `1` | Everything else: the registry was unreachable, refused the key, or answered with an error. |

Several failures moved from `1` to `2`, and a push refused by the registry moved
from `2` to `1`. If a script compares exit codes to specific values, check them
against this table.

### Stricter input

* An unknown `--output` value is rejected with exit code `2`. v1 silently fell
  back to `human`.
* `list`, `info`, `push` and `build --push` require an API key and fail with
  exit code `2` before any network call when it is missing. `init`, `build`
  (without `--push`), `manifest` and `self-update` do not need one.
* `build --header` requires the `Name=value` form. A value without `=` (e.g.
  `--header "Version: 1.0.1"`) fails with exit code `2`; v1 silently ignored it.
* `info` requires a slug.
* `init` always turns an explicit slug into a valid one (`my_plugin` becomes
  `my-plugin`).

### Standard output and standard error

In `human` and `plain` modes, stdout only carries the answer. Errors, progress
(now one line per step instead of a progress bar) and notices go to stderr.

### JSON answers

* Every error is one object on stdout, `{"code", "message", "errors"}`, where
  `code` is the HTTP status or the exit code, never `0`.
* `-q/--quiet` no longer suppresses the JSON answer.
* Slashes are no longer escaped (`"https://…"` instead of `"https:\/\/…"`).
* New shapes:
  * `init` answers `{"path": "…"}`;
  * `manifest --get <Header>` answers `{"<Header>": "value"}`, e.g.
    `{"Version": "1.0.0"}`;
  * `self-update` answers in JSON;
  * `wpc` and `wpc list` answer `{"usage", "commands", "options"}`.

See [Scripting wpc](/cli/usage#scripting-wpc) for the full contract.

### In a terminal

* `list` and `info` are interactive: browse with the arrow keys. Use
  `--output=plain` or `WPC_NO_TUI=1` for the static tables.
* `init` opens a wizard; the line-by-line questions remain outside a terminal.
  Options passed on the command line are no longer overwritten by the defaults,
  and the name is optional (it is asked for, or fails with exit code `2` under
  `-n`).
* `init --no-interaction` now fills in the `Author` and `Author URI` known to
  your organization when you do not pass them, as the interactive mode does.
* Tables have a new style, and the theme list shows `downloaded`,
  `creation_time` and `description`.
* The "Did you mean… run instead?" suggestion is gone.

### Docker image

* `latest` now runs PHP 8.5 instead of 8.2. Use the `php8.2` tag, or
  `<version>-php8.2`, to stay on PHP 8.2.
* The image is slimmer: it keeps the `zip` extension, composer, git and unzip,
  but drops the other PHP extensions (pdo, gd, intl, bcmath…). If your build
  needs them, use your own image (see [Integrate in your CI/CD](/cli/automate)).

## New in v2

* The `<noun> <verb>` grammar, `wpc help` and shell completion.
* [`wpc self-update`](/cli/install#keep-wpc-up-to-date), with `--check`,
  `--rollback` and `--major`.
* [Interactive mode](/cli/usage#interactive-mode) and the `WPC_NO_TUI`,
  `WPC_ACCENT_COLOR`, `WPC_NO_UPDATE_CHECK` and `WPC_NO_DEPRECATED_WARNING`
  environment variables.

## Discovering the commands

`wpc` on its own now lists the two nouns rather than every command at once:

```bash theme={null}
wpc              # what wpc can manage
wpc plugin       # what you can do to a plugin
wpc plugin push --help
```

Shell completion follows the same shape — <kbd>Tab</kbd> after `wpc plugin`
offers the verbs:

```bash theme={null}
eval "$(wpc completion bash)"   # or zsh, fish
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.