cwp ability
shipped 1.0.0cwp ability <name> [json] [env] [flags]
Acts on the local site. Name an environment to act there instead.
| Argument | What it is | Default |
|---|---|---|
<name> | ability name, e.g. bricks/get-page-elements | |
[json] | JSON input object. A leading { tells it from [env] | |
[env] | environment to call on (default: default_environment in cwp.yml) |
| Flag | What it does | Default |
|---|---|---|
--input-file <path> | read the JSON input from a file instead | |
--all | follow hasMore and return every page (B-017) | off |
--from <repo-path> | the committed file this payload comes from (P2) | |
--adhoc | accept that this change is not reproducible, and record it | off |
--force | override the protected-environment refusal | off |
--no-backup | skip the remote backup taken before the write | on |
--no-snapshot | skip the local design-system export taken before a destructive call | 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
Calls one ability by name. It is the plain door onto the WordPress Abilities API:
the name pattern accepts any namespace, and everything cwp does not wrap would
otherwise need a throwaway wp eval-file script.
The result goes to stdout as pretty-printed JSON, so it pipes into jq. With
--json it moves into the envelope’s data.result instead, because that stream
may only ever carry one object.
The leading brace tells the input from the environment. Every ability takes a
JSON object, so cwp ability bricks/get-mcp-version dev and
cwp ability bricks/get-page-elements '{"slug":"x"}' dev both parse. cwp refuses
the reverse order by name rather than silently reordering it. --input-file
takes the same JSON from a file, for payloads too big to quote.
A namespace mistaken for another gets an answer rather than a guess:
✗ "bricks/get-posts" is not registered on this site
→ did you mean `snn/get-posts`? — run `cwp abilities` to see all 175
The guards come from the ability, not from a flag
A general-purpose door onto production is only safe if it knows which calls
write. The abilities say so themselves, in their readonly, destructive and
idempotent annotations.
A read runs unguarded, and runs under --dry-run for real. Anything else
against a remote takes the full guard set: a protected environment refuses
without --force, cwp asks for confirmation and takes a remote backup first.
Under --dry-run cwp describes a write and does not run it.
cwp treats an ability that declares nothing as a write, and says so. The SNN
namespace annotates none of its 24, so snn/get-posts gets the guards despite
being a getter. Rounding that way is deliberate: guarding a read costs a
confirmation, and letting an undeclared write through against production costs
the thing this tool exists to prevent.
An upward write needs a committed source
The applier refuses any effect that changes a remote with nothing in the
repository behind it. cwp push has its tracked paths,
cwp push --only inventory has inventory.yml, and
cwp push --only bricks has the bricks/ tree. An ad-hoc ability call is the
one place in the tool with no such file. So a write against a remote takes one
of two flags:
--from <repo-path>names the committed file the payload came from, and is the normal form.--adhocdoes not waive the rule, it records it. cwp writes the payload tocwp/adhoc/<timestamp>-<ability>.jsonbefore the call, and the run says out loud that the change is not reproducible. A protected environment refuses it outright: there, “I accept this is not reproducible” is not an answer anybody should give in passing.
Reads need neither, and a call against the local site needs neither.
--all, and why it is not the default
Every Bricks listing ability answers with 25 items and reports the rest in
total and hasMore beside them. Reading items and moving on means silently
working with a third of the site. That has cost real time on a real project
(B-017).
The default is one page, because a caller piping into jq should get what it
asked for. The warning is not optional:
! "bricks/list-global-classes" returned 25 of 32 items and there are more —
pass --all to follow the pages (B-017)
--all follows hasMore and returns one merged listing with hasMore cleared.
On an ability that takes no page argument it is a no-op with a warning, not an
error.
The design system gets a restore point first
A destructive call in a design-system category (bricks/delete-global-class and
its neighbours) takes a local export into cwp/bricks-snapshots/<timestamp>/
before it runs. Bricks keeps no revisions of those items: a delete is
immediate and final, and an export is the only way back. --no-snapshot waives
it and says what you are waiving. Against a remote the provider’s backup already
covers it, so the snapshot is local only.
An unrecognised category snapshots too. Silence is not a licence. cwp reads an
ability that declares neither readonly nor destructive the same way.
Example
cwp ability bricks/get-page-elements '{"slug":"about-us"}'
cwp ability bricks/list-global-classes --all
cwp ability bricks/import-transfer-package --from bricks/ prod
cwp ability bricks/set-page-settings '{"postId":42,"settings":{}}' prod --adhoc
What it does not do
It does not validate your input against the ability’s schema. Bricks does that,
and cwp adds the list of accepted properties to the error. There is no
wp ability command to print one.
It does not make an unreachable ability surface reachable. It does not soften an ability’s own annotation: there is no flag that says “trust me, this one is a read”.