WP-CLI Commands
BuddyNext registers up to six WP-CLI command namespaces in Free: wp buddynext demo (the demo-data seeder), wp buddynext cert (the functional-certification harness), wp buddynext repair-space-owners (a one-off orphan sweep), wp buddynext repair-discussion-visibility (a one-off visibility sweep for discussions provisioned before visibility was derived from the space type), wp buddynext handles (check / repair member handles that mentions cannot parse), and wp buddynext qa-fixtures (deterministic QA data - development trees only). All are registered in Plugin::init() and load only when WP-CLI is running. This page documents their subcommands, what they seed or verify, and example invocations.


Overview
Section titled “Overview”if ( defined( 'WP_CLI' ) && WP_CLI ) { \WP_CLI::add_command( 'buddynext demo', new \BuddyNext\Demo\DemoCommand() ); \WP_CLI::add_command( 'buddynext cert', new \BuddyNext\Cert\CertCommand() ); \WP_CLI::add_command( 'buddynext repair-space-owners', \BuddyNext\Spaces\SpaceOwnerRepairCommand::class ); \WP_CLI::add_command( 'buddynext repair-discussion-visibility', \BuddyNext\Bridges\DiscussionVisibilityRepairCommand::class ); \WP_CLI::add_command( 'buddynext handles', new \BuddyNext\Profile\HandleCommand() );
// Registered only when dev/QaFixturesCommand.php is present. $bn_qa_fixtures = BUDDYNEXT_DIR . 'dev/QaFixturesCommand.php'; if ( is_readable( $bn_qa_fixtures ) ) { require_once $bn_qa_fixtures; \WP_CLI::add_command( 'buddynext qa-fixtures', new \BuddyNext\Dev\QaFixturesCommand() ); }}The demo command is a thin wrapper over DemoDataService, so the CLI and the admin “Demo Data” button share one engine. The cert command wraps CertRunner, the same gate that bin/check.sh and CI run.
qa-fixturesdoes not exist in a packaged install. It lives indev/, which is not onbin/build-release.sh’s runtime allowlist, so the file is absent from the shipped zip and theis_readable()guard above never fires. It is a development-tree command. Do not write docs, support replies, or tooling that tells a customer to run it.
wp buddynext demo
Section titled “wp buddynext demo”Populates, inspects, or removes a realistic demo community. Useful for screenshots, manual QA, and verifying behavior against a populated dataset rather than five empty rows. The seeder uses bundled offline images, so it works with no network access.
Subcommands
Section titled “Subcommands”| Subcommand | What it does |
|---|---|
seed |
Populates the demo community: members, spaces, posts, the social graph between them, and profile fields. Refuses to run if demo data is already installed - run cleanup first. |
status |
Prints what is currently installed: counts of members, spaces, posts, and profile fields. Prints “No demo data installed.” when the dataset is absent. |
cleanup |
Removes everything the seeder created (posts, spaces, members, profile fields) and reports the counts removed. |
What seed creates
Section titled “What seed creates”The seeder produces a connected community, not isolated rows:
- Members - demo users with avatars (bundled offline images) and populated profiles.
- Spaces - demo spaces with members assigned to them.
- Posts - activity posts authored across the members and spaces.
- Social graph - follow / connection relationships between the demo members.
- Profile fields - the custom profile fields the demo profiles fill in.
seed is idempotent-guarded: if DemoDataService::is_seeded() reports data already present, it warns and exits instead of double-seeding. cleanup is the inverse and is similarly guarded - it warns if there is nothing to remove.
Examples
Section titled “Examples”# Populate a demo communitywp buddynext demo seed
# See what is installedwp buddynext demo status
# Remove everything the seeder createdwp buddynext demo cleanupSample seed output:
Seeded 24 members, 6 spaces, 80 posts, 9 profile fields.Sample status output:
Members: 24Spaces: 6Posts: 80Profile fields: 9Note: The exact counts depend on the bundled dataset; the numbers above are illustrative. Re-running
seedwithout first runningcleanupis a no-op that warns - it never duplicates the dataset.
wp buddynext cert
Section titled “wp buddynext cert”The functional-certification harness. It is the one trustworthy release gate that asserts the plugin behaves - toggles actually enforce and REST routes do not fatal - rather than that the code merely parses or passes a linter. It is invoked by bin/check.sh and CI.
Subcommands and flags
Section titled “Subcommands and flags”| Invocation | What it runs |
|---|---|
wp buddynext cert |
Runs all checks (contract + boot). Exits 1 if any check fails. |
wp buddynext cert contract |
Runs only the contract (dead-toggle / behaviour-flip) check. |
wp buddynext cert boot |
Runs only the REST boot smoke - dispatches every public GET route and asserts none return 500. |
wp buddynext cert --porcelain |
Emits the ledger as machine-readable JSON (for the MCP and CI) instead of the human summary. Combine with a check name to scope it. |
Note: The machine-readable flag is
--porcelain, not--json. WP-CLI reserves--jsonfor its own output formatter and would reject it.
The contract check (the cert contract)
Section titled “The contract check (the cert contract)”This is an internal QA gate, and its inputs do not ship. The command is in the plugin, but the inventory and oracle files it reads live outside the distributed package by design - the internal surface inventory is deliberately not public. On a normal install the runner therefore finds no oracles and reports holes rather than passes. That is expected, and it refuses to report a vacuous “0 failures” pass when it has asserted nothing. Documented here because the command exists and you will find it; you are not missing a file you were supposed to have.
The contract check proves that every gated setting is wired through to real behavior, catching “dead toggle” bugs - a setting saved in the database but never read on the enforcement path.
For each gated feature listed in its contract oracle, the runner:
- Snapshots the current setting state.
- Flips the setting OFF and asserts the REST surface’s behavior changes - the disabled error code appears.
- Flips the setting ON and asserts the disabled error code is gone.
- Restores the original state.
Each oracle yields a row with one of three statuses:
| Status | Meaning |
|---|---|
PASS |
The toggle enforces - behavior changed when flipped. |
FAIL |
The toggle is dead - flipping the setting did not change behavior. Fails the gate. |
HOLE |
The feature is toggleable but has no oracle, so enforcement is unproven. On a normal install every gated feature reports this, because the oracle file is not part of the distributed package. |
A HOLE is uncovered surface, not a failure, but it signals a gap in the oracle.
The boot check
Section titled “The boot check”The boot check dispatches every public/GET REST route under the BuddyNext namespaces and asserts none return >= 500 (a thrown fatal is captured as a 500). A 4xx (for example an auth-required 401/403) is acceptable - only server faults fail the gate.
Examples
Section titled “Examples”# Full functional certification (contract + boot); exits 1 on any failurewp buddynext cert
# Only the dead-toggle behaviour-flip checkwp buddynext cert contract
# Only the REST boot smokewp buddynext cert boot
# Machine-readable ledger for CI / MCPwp buddynext cert --porcelainSample human output:
PASS contract feature-x disabled code appears when off PASS boot GET /spaces 200 FAIL contract feature-y flip had no effect HOLE contract feature-z no oracle - enforcement unproven
2 passed, 1 failed, 1 holes (uncovered)Error: Functional certification FAILED - 2 passed, 1 failed, 1 holes (uncovered)wp buddynext repair-space-owners
Section titled “wp buddynext repair-space-owners”A one-off sweep for spaces whose owner_id points at a user who no longer exists.
Space succession (auto-promoting an heir when an owner is deleted or erased) guards deletions from now on. It cannot retroactively fix a space orphaned before it shipped. This command finds those spaces and runs them through the same SpaceSuccession path, chunked 200 rows at a time so it survives a large install.
It takes no subcommand - invoke it directly. One flag:
| Flag | What it does |
|---|---|
--dry-run |
Report what would change without writing anything. |
# See what it would do first.wp buddynext repair-space-owners --dry-run
# Then let it write.wp buddynext repair-space-ownerswp buddynext qa-fixtures
Section titled “wp buddynext qa-fixtures”Deterministic QA data: the ugly states a customer demo must never contain (expired invites, orphaned space owners, cancelled subscriptions, rows backdated past the retention windows) plus big-site scale data.
This is not the demo seeder. demo builds a community that looks good; qa-fixtures builds the states that break things, so QA stops guessing at them.
Development trees only. As above,
dev/is not shipped, so this command does not exist in a packaged install.
Subcommands
Section titled “Subcommands”| Subcommand | What it does |
|---|---|
seed |
Creates the fixtures for the chosen profile. |
cleanup |
Removes what seed created. |
status |
Prints what is currently installed. |
seed takes one flag:
| Flag | Default | Options |
|---|---|---|
--profile=<profile> |
edge |
edge, community, scale, all |
wp buddynext qa-fixtures seed # edge cases (the default)wp buddynext qa-fixtures seed --profile=community # a populated communitywp buddynext qa-fixtures seed --profile=scale # big-site scale datawp buddynext qa-fixtures seed --profile=all # everything
wp buddynext qa-fixtures statuswp buddynext qa-fixtures cleanupNotes / gotchas
Section titled “Notes / gotchas”demoandcertdeclare@when after_wp_load, so WordPress is fully loaded before they run - they have access to services, settings, and the REST router.certwrites a ledger as a side effect of every run, so CI and the MCP can read the last result without re-running the gate.demoandcertare Free commands. Pro registers one WP-CLI command of its own -wp buddynext-pro cert(\BuddyNextPro\Cert\CertCommand, added in the ProPlugin::init()) - the same functional-certification harness scoped to Pro’s gated features. It takes the same optionalcontract/bootpositional and--porcelainflag. Free’scertoracle covers gated features in Free.
See also the Cron and Async Jobs page for the scheduled-job surface these tools run alongside.

