Search by

leestratman / wp-content-bundle

LeeStratman

Export and import WordPress content bundles: portable slices of content with their media, for fixtures and test sites. A declared format (spec/) with a WP-CLI implementation.

Package info

github.com/LeeStratman/wp-content-bundle

Type:wp-cli-package

pkg:composer/leestratman/wp-content-bundle

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.0 2026-11-04 19:57 UTC

This package is auto-updated.

Last update: 2026-11-04 19:57:46 UTC


README

A content bundle is a portable slice of a WordPress site's content: posts of chosen types with their meta, terms, authors, comments and the media they use, as a directory you can commit, review, and load into any WordPress that registers those post types. Seed an e2e site with real-shaped content, share a fixture between projects, reproduce a bug against the content that triggered it.

This repository is the format and its reference implementation:

  • spec/ — the format (version 1.1): what's in bundle.json, the import rules a reader follows, versioning, privacy. spec/schema.json is the JSON Schema; spec/examples/minimal is a real bundle.
  • wp content-bundle — a WP-CLI package that exports, imports and removes bundles.
  • ContentBundle\… — the same, as plain PHP functions a plugin can call (src/functions.php).

It is not a backup: ids are reassigned on import, references are rewritten to match, and personal data is scrubbed on export by default.

campaigns/            any name — a directory is a bundle because it holds bundle.json
  bundle.json         manifest + posts, users, media, comments (+ optional site_config)
  media/12-hero.jpg   the files of every attachment the posts use

Use it

# Export: personal data scrubbed, media files included
wp content-bundle export --post-types=page,campaign --output=tests/Fixtures/campaigns

# Import, replacing whatever the last import of this bundle created
wp content-bundle import tests/Fixtures/campaigns --replace

wp content-bundle import tests/Fixtures/campaigns --dry-run    # what would happen
wp content-bundle remove tests/Fixtures/campaigns              # take it back out
Export option
--scrub-meta=k1,k2 Also blank these meta keys (names, phone numbers — what a pattern can't spot). * allowed. The report names keys where emails turned up.
--content-meta=k1,k2 Meta keys that are page content (pages built from ACF or other custom fields): left as published, like post content. * allowed. The report suggests this for ACF fields where it found emails.
--keep-personal-data Don't scrub. Local use only.
--include-config Add allowlisted options, theme and plugins as site_config.
--overwrite Replace an existing bundle; it keeps its id, so --replace still matches.
--output=x.json One file instead of a directory; media then imports by URL.
Import option
--replace First remove what an earlier import of the same bundle created.
--dry-run Report per post type what would import or be skipped.
--skip-media Import no media (offline, deterministic).
--with-config Also apply site_config.
--force Write to a site not marked local or development.

Imports refuse unless WP_ENVIRONMENT_TYPE is local or development. Posts whose type the site doesn't register are skipped and reported, never inserted, so activate the theme or plugin that registers them first.

Install

In a project, with Composer (it's a wp-cli-package; Composer's autoloader loads it):

{
  "repositories": [{ "type": "vcs", "url": "https://github.com/LeeStratman/wp-content-bundle.git" }],
  "require-dev": { "leestratman/wp-content-bundle": "^1.0" }
}

Then point WP-CLI at it: wp --require=vendor/leestratman/wp-content-bundle/command.php …, or in wp-cli.yml:

require:
  - vendor/leestratman/wp-content-bundle/command.php

Globally: wp package install https://github.com/LeeStratman/wp-content-bundle.git

From JS tooling (to mount the PHP into a container, or validate bundles against the schema): pnpm add -D github:LeeStratman/wp-content-bundle#v1.0.0, then wp-content-bundle/schema.json.

command.php is safe to load more than once and outside WP-CLI, where it only defines the library.

Versions

The package follows semver. The format has its own format_version (MAJOR.MINOR, see the spec): readers refuse a format major they don't implement and ignore fields they don't know, so format minors add only optional fields. A package major is the place for a format major.

Developing

tests/smoke     # the spec's import rules against a real WordPress; needs only Docker

Change the spec and the code together: a rule in spec/README.md that the smoke test doesn't check is a rule nothing holds the code to.

Origin

Extracted from WordPress Sidekick, which still writes and reads bundles (sk export / sk import) through this package. Bundles Sidekick wrote before format 1.0 (*.skpkg directories with package.json) still import.

License

GPL-2.0-or-later, like WordPress. See LICENSE.