The build loop
shipped 1.0.0cwp has no build command and is not going to get one. What it has is a cycle, and the cycle is the product. Every command below exists because a step in it needed one.
This page is that cycle, end to end. It holds for any project cwp manages. A site with a page builder runs one more command than a site without, and nothing else about it changes.
The loop
cwp db pull # 1. production's database, into the local container
# 2. build — in the browser, or through an MCP client
cwp pull # 3. the tree, out of the database into files
git diff # 4. read what you actually changed
git commit # 5.
cwp deploy dev # 6. the tree and the files, upward
Six steps, and the two halves are not symmetrical: down is a copy, up is a
diff. cwp db pull replaces the local database wholesale. That makes it safe
to run whenever you are unsure what state you are in. A push sends named
things and refuses the ones it cannot place.
Step by step
1. cwp db pull: start from what is live
cwp db pull imports the environment’s database into
the local container, scrubbed and rewritten for the local URL. The mail guard
goes in whether or not scrubbing ran. Uploads come down as a proxy rather than
a copy. The first run against an image-heavy site therefore takes about two
minutes rather than an hour. cwp media pull
copies them when you want them local.
The database and the tree are different commands, and step 3 is the other one. This step gives you a site to work in; that one gives you files to review.
Take a snapshot before you begin if you want a point to return to:
cwp db snapshot.
2. Build
In the Bricks builder, in wp-admin, or through an MCP client talking to the site’s abilities. cwp is not involved and does not want to be. The work happens in this step, and the tool’s job is to be absent during it.
3. Pull what you built: the step people skip
Everything you built lives in the database: the design system in options,
the pages in postmeta. cwp deploy moves files. A
deploy after a build session therefore ships nothing you did, reports success,
and is the single most common way to lose an afternoon with this tool.
cwp pull # the design system, the pages, terms, menus, settings,
# widget areas, roles and the inventory → files
One command, and it writes a tree of files rather than touching the site. It is safe to re-run: a pull that changes nothing writes nothing. It carries every artifact at once. A partial read leaves a baseline that means nothing in particular.
Narrow it with --only when you know what you touched:
cwp pull --only bricks # colours, typography, classes, templates → bricks/
Check what came out before committing:
cwp status --drift
That compares the local site against the committed tree and says which is ahead.
It costs a container. A bare cwp status does not, and
still runs offline in half a second.
4–5. Read the diff, then commit
git diff bricks/ content/ is the review step, and it is readable on purpose.
The trees are canonical JSON and YAML with names in place of environment-local
ids, so a change to a colour is one line rather than a re-serialised blob.
Here the tree becomes the record. Everything after it moves what you committed, never what sits in a database.
6. cwp deploy: everything, upward
cwp deploy is cwp push plus
the remote post-steps and the post-deploy hook. The push carries both halves
of what you built: the six artifacts out of the tree and the tracked files.
One confirmation lists every page, every image it would upload and every
attachment whose text it would overwrite. Terms first, then pages parent-first,
then the navigation.
One command for both is the reason this list is six steps: the pages and the files go up together, and neither can be the one you forget.
Where the loop is guarded
- Nothing moves up by default. Database and uploads flow downward; the
upward writes are individually named commands, and each refuses a
protectedenvironment without--force. - cwp refuses a conflict, never merges it. If the target changed since cwp last saw it, the push stops and names the page.
- cwp takes a remote backup before any upward write, unless you disable it deliberately.
The safety model is the full account.
Making the loop enforce itself
Two optional habits, neither of them cwp’s policy to impose:
A pre-push gate. cwp init scaffolds
cwp/hooks/pre-push.sh with the line commented out:
cwp status --fail-on-drift
Uncomment it and a deploy aborts while the local site is ahead of the tree: step 3 forgotten. It fails on a column it could not read rather than passing, so a stopped container is a stop and not a green light.
A snapshot before each pull, and you get it for free: every pull leaves
pre-pull-<env>-<timestamp>. cwp status reads
“last pull” from there too.
What this loop is not
It is not continuous deployment. There is no watcher, no daemon and no auto-push. Every upward step is a command somebody ran on purpose, after reading what it said it would do. The safety model says why.