cwp adopt
shipped 1.0.0-rc.2cwp adopt <env> [flags]
Acts on the environment you name. There is no local default, so you name one.
| Argument | What it is | Default |
|---|---|---|
<env> | environment to adopt |
| Flag | What it does | Default |
|---|---|---|
--release | take it back: remove cwp’s identity and records | off |
--rescope | re-derive what is under management, as a diff to consent to | off |
--force | override the protected-environment refusal | off |
--no-backup | skip the remote backup taken before the write | on |
--yes | skip the confirmation prompt | off |
--with-agent | with —dry-run on a host with no shell: install and remove the PHP agent so the plan is real | off |
Plus the shared flags --json, -v, --verbose, -q, --quiet and --dry-run.
What it does
Declares that this project manages a site, and gives its content the identity that makes every later crossing possible.
It writes to the site. A uid changes what the site is and stays there
until something removes it, so cwp adopt asks before it does, naming the posts
it would adopt.
cwp adopt prod --dry-run
The dry run answers a question nothing else does: this is what I would manage, and this is what I would write, before cwp writes anything. It prints the scope it would derive (post types, taxonomies, widget areas, roles) and names the types it would not take without a decision:
✓ would adopt — "prod" — 10 post(s) would be given an identity
page/home → #17, claimed by the tree on its slug
page/about → #11, claimed by the tree on its slug
page/careers → #2, a new identity — the tree does not describe it
…and 7 more
✓ scope — 2 post type(s) · 2 taxonom(ies) · 1 widget area(s) · 5 role(s)
registered by a plugin or the theme, and not taken without a decision:
product 1,284 entries
shop_order 412 entries
The two answers per post are not the same decision. A page claimed by the tree becomes that tree item, and stays it: the next push writes the file over that page. A page the tree does not describe gets an identity of its own. cwp manages it from then on, with nothing in the repository describing it yet.
Read them before the yes. A slug matched to the wrong post duplicates a page and leaves the original holding the URL.
That list is where transactional data belongs: visible, unmanaged, and a decision somebody makes rather than four thousand orders arriving in a repository.
Adoption is standing, not repeated. Afterwards, content cwp has not seen before gets an identity without a new prompt. You took the decision once. The output still names every minting.
That naming carries the same answers the plan carried, in the same words:
✓ page/home — adopted as 5f5a9e54-… (claimed by the tree on its slug)
✓ page/d9f77deb-… — adopted as d9f77deb-… (claimed by the tree on the last transfer's record)
✓ page/careers — adopted as f3c1b204-… (a new identity — the tree does not describe it)
There are three answers because the pairing has three keys. cwp reads them in
this order: the identity the post already carries, then what the last transfer
to this environment recorded, then the slug. The middle one carries a site
that lost its _cwp_uid to a restore or a migration while the tree stayed
intact. cwp wrote those posts, and its ref
remembers which post each item was. It never reads another environment’s ref,
and it declines where the post type disagrees.
What the target does not hold
Adoption pairs two sides. The run names the other side too: the tree items no post on the environment claims.
! 4 tree item(s) have no counterpart on "prod" — the next push creates each of them as a new post
page/d9f77deb-… content/page/d9f77deb-….yml
→ same title as #4711: cwp wp --env prod -- post meta update 4711 _cwp_uid d9f77deb-…
That list is the set a push would create a second time. A draft has no slug:
wp_insert_post derives post_name only for a status that is publicly
addressable. So nothing pairs the draft with the post it already is on the
site, and pushing makes a second one.
Where a leftover item and a post this run gave a fresh identity to carry the same title, cwp names the pair and prints the command that settles it. It does not run it. A title is not an identity. The slug key declines a guess because nobody can undo adopting the wrong post. So the decision goes to whoever can recognise the post. The cleanup is one paste rather than four duplicates. A title two items share, or two posts share, names nothing, and cwp does not offer it.
Taking it back
cwp adopt prod --release
Removes the identity from every post, the sync marker beside it, the adoption record, the provenance options and the dashboard widget. It says how many of each it took off:
✓ release — "dev" is no longer adopted — removed 7 identities, 6 sync marker(s), cwp_pushes, cwp_last_push, the dashboard widget
The count is there because a release that cleared nothing must not read like one that cleared everything. Anything left on the site afterwards is a warning, not a tick.
It refuses while the tree still holds items tracked against that environment. Releasing then would orphan those identities in silence. The files keep their uids and the site loses them. The next push then adopts by slug and duplicates everything.
The ref survives, marked released, so the log of what happened stays true.
What it does not do
- It does not adopt a
sourceenvironment. That mode is read-only by declaration, and--forcedoes not override it. The refusal is a target that does not exist rather than a guard that fired. - It does not resolve a disagreement. If the site carries an adoption record this checkout knows nothing about, another checkout adopted it. cwp says so and chooses nothing. Adopting again would mint a second identity over the first.
- It does not pull anything. Adoption writes identity and records the scope.
Reading the environment into the tree is
cwp pull: a separate decision and a separate command.