# Clone a package version

> Publish a new package version behind the same aliases at a handoff hour.

Source: https://metrocli.com/docs/guides/clone-a-package-version/ · Docs index: https://metrocli.com/llms.txt

## Goal

Publish a new version of the `growth` package that takes over the alias at 1 January 2027, 00:00 UTC, and switch its usage statements to the contract anniversary. Contracts created from that hour get the new version. Existing contracts keep the version they were created from.

Packages can't be edited, so a new version is a fresh package create whose alias entry starts at the handoff. From that hour, alias resolution moves to the new version. See [Packages](/docs/concepts/packages).

## Preview

```bash
metro package list --search=growth --sandbox --json
metro package clone-version preflight --aliases=growth --handoff-at=2027-01-01T00:00:00.000Z \
  --usage-day=CONTRACT_START --sandbox --out=plans/clone.json
```

`--aliases` takes a comma-separated list, so one plan can roll several packages at once. For each alias, preflight:

- reads the version live now and copies it into a new create body;
- sets the alias on the new version to start at `--handoff-at`, which must be a future UTC hour;
- changes `usage_statement_schedule.day` only if you pass `--usage-day` (`CONTRACT_START` or `FIRST_OF_MONTH`);
- bumps the `uniqueness_key`, and skips an alias whose new key already exists, so a re-run creates nothing twice.

It blocks with `alias_not_live` when no version is live, and with `alias_already_has_a_future_version` when a handoff is already scheduled. The diff shows, per alias:

```text
  growth.usage_statement_schedule.day: "FIRST_OF_MONTH" -> "CONTRACT_START"
  growth.resolves_to: "00000000-0000-4000-8000-000000000104" -> "(new version) from 2027-01-01T00:00:00.000Z"
Steps: POST /v1/packages/create
Payload hash: sha256:...
```

To change prices or terms in the new version, write a full spec instead and run `metro package create preflight --file=package.yaml --allow-alias-takeover --sandbox`, with a future `starting_at` on the alias. Preflight warns `MTR-PKG-004` that the alias moves.

## Confirm

Show the human each alias, the handoff hour, what changes, and the hash. Check who's on the old version with `metro package customers --alias=growth --sandbox`. Then dry-run:

```bash
metro package clone-version apply --file plans/clone.json --sandbox --confirm-hash sha256:...
```

## Apply

```bash
metro package clone-version apply --file plans/clone.json --sandbox --confirm-hash sha256:... \
  --apply --confirm-live-apply=I_UNDERSTAND_THIS_WILL_WRITE_LIVE_METRONOME_SANDBOX
```

Nothing is archived. When you later retire the old version, check it offline first: `metro package archive preview --file handoff.json --sandbox` refuses an archive until the replacement alias is live and read back. Archiving before then makes contract creation fail with `400`.

## Readback

metro reads the new package back, compares it with the plan, and proves both sides of the handoff:

```text
Applied (sandbox).
Read-back (expected vs actual):
  ok   growth.name: expected "Acme Growth" actual "Acme Growth"
  ok   growth.rate_card_id: expected "00000000-0000-4000-8000-000000000103" actual "00000000-0000-4000-8000-000000000103"
  ok   growth.usage_day: expected "CONTRACT_START" actual "CONTRACT_START"
  ok   growth.alias_starting_at: expected "2027-01-01T00:00:00.000Z" actual "2027-01-01T00:00:00.000Z"
  ...
  ok   growth resolves to predecessor before handoff: expected "00000000-0000-4000-8000-000000000104" actual "00000000-0000-4000-8000-000000000104"
  ok   growth resolves to new version at handoff: expected "00000000-0000-4000-8000-000000000204" actual "00000000-0000-4000-8000-000000000204"
```

The full list also covers the uniqueness key, duration, usage frequency, billing provider, and subscription, credit and commit counts. Illustrative IDs; the check names are exact. Any `FAIL` exits `3`.
