Schema Sync
Pull, push, diff, and compare field and template schemas between ProcessWire sites.
What schema sync does
Schema sync lets you export, import, diff, and compare your ProcessWire field and template definitions between sites. This is useful for keeping development, staging, and production environments in alignment.
Schema files
Schema is stored as two JSON files under .pw-sync/schema/:
fields.json: all non-system fields with their type, inputfield, label, description, and type-specific settings.templates.json: all non-system templates with their field list, family settings, access rules, and cache configuration.
These files are portable. You can commit them to version control and use them to provision new environments.
Pull schema
Export the current site's schema to local files:
Pull the site schema.
pw_schema_pull overwrites fields.json and templates.json with the current state. Before overwriting, it creates .bak copies of the existing files so a mistaken pull is recoverable.
Push schema
Apply local schema files to a ProcessWire site:
Push the schema to ProcessWire. Dry-run first.
pw_schema_push reads the local JSON files and creates or updates fields and templates to match. Fields are processed before templates so that template field lists can reference newly created fields.
Schema push is additive: it creates missing fields and templates and updates existing ones, but it never deletes fields or templates. It also does not change a field's type (e.g. from FieldtypeText to FieldtypeTextarea) because that could destroy data.
Diff schema
Compare your local schema files against the live site:
Show me the schema diff.
pw_schema_diff reports fields and templates that exist locally but not in ProcessWire (and vice versa), plus any settings that differ.
Compare two sites
Compare schemas between two environments without modifying either:
Compare the local schema against production.
pw_schema_compare fetches the schema from both sites and reports differences. You can compare current (the locally configured site) against production or any named site configured in .pw-sync/sites/.
Named sites are configured as JSON files (see Configuration).
Edit a template's fieldgroup
Schema push (above) creates and updates field and template definitions, but it doesn't touch fieldgroup membership: which fields are attached to a template, in which order, and with which per-template overrides. That's pw_template_fields_push:
Add a member_first_name field to the blog_post template on both sites. Dry-run first.
The tool supports three operation verbs and one context block:
add: attach existing fields to the template's fieldgroup. Accepts mixed strings and{name, context}objects in the same array, so you can attach a field and set its per-template overrides in one call.remove: detach fields from the fieldgroup. The field definition itself is preserved (use the upcomingpw_field_pushin v1.12 to delete definitions).reorder: rearrange fields within the fieldgroup. The reorder uses an in-place insert so global fields liketitlecan be moved without ProcessWire refusing to remove them.- Per-fieldgroup context: override a field's label, description, required, columnWidth, showIf, requiredIf, or collapsed setting just for this template. FieldtypePage fields can also override
template_id,parent_id,findPagesSelector, andinputfield.
Conflict classifier
Every planned change is tagged with one of three severity levels:
safe: standard edits with no detected risk. Apply freely.warning: visible but non-blocking. The write proceeds. Examples: removing a field whose name matches a known module convention (seoneo_*,form_*, etc.) on a non-module-owned template; an added Page reference field with no selectable-pages constraint; an added File or Image field with no extensions whitelist.danger: blocks the write unlessforce: trueis also passed. Examples: removing a system or permanent core field (title,pass,roles); editing a template owned by ProcessWire core (admin,user,role) or by FormBuilder, MediaHub, or ProFields; removing a field that is required on this template; an edit that would leave aFieldsetOpenorFieldsetTabOpenwithout its matching_ENDclose.
The classifier is module-aware: removing blog_categories from blog_post is safe; removing mediahub_collection from a MediaHub-owned template fires a danger; removing seoneo_title from a content template fires a warning so the operator sees the cleanup is happening on a known module convention.
Frontend-usage scan
Before any remove operation is reported, PromptWire walks site/templates/ and grep-checks for hardcoded references to the field name. If your blog listing template includes $pages->find("template=blog_post, sort=-blog_date"), removing blog_date surfaces a warning listing each file, line number, and matching snippet. Word-boundary matching keeps substring false positives out (blog_ does not match blog_date). The scan is a warning, not a blocker, so a legitimate field retirement can still proceed once you have read the references.
Cross-site fieldtype drift
When called with site: "both", the MCP layer compares the projected post-push fieldgroup on each side name-by-name. Any field that exists on both sides with a different fieldtype class (for example, FieldtypeImage on production and FieldtypeCroppableImage3 locally) is emitted as a danger in a top-level crossSite block. The push refuses to proceed until the drift is resolved, so a well-meaning agent cannot quietly normalise a fieldtype mismatch by overwriting one side with the other.
Dry-run by default, with an audit trail
Like every other write tool, pw_template_fields_push defaults to dryRun: true. The dry-run response includes the current fieldgroup, the planned post-push fieldgroup, and the full conflicts list. A real write returns the same plus an audit object listing what was removed, added, reordered, and how many save() calls fired, so partial writes surface their exact stopping point.
Fieldgroup membership vs field definitions
pw_template_fields_push covers fieldgroup membership and per-template context only. Field definitions, the fieldtype, inputfield class, parent picker, options list, and so on, are owned by pw_field_push (planned for v1.12). The two tools split deliberately: fieldgroup edits are common and recoverable; field-definition edits are rare and can destroy data, so they get their own classifier and gating.
FieldtypeOptions support
Schema push supports FieldtypeOptions fields. If the local schema defines option values that don't exist on the live site, they are added after the field is saved. Existing options are not removed or reordered.
Last updated