Skip to content

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.

The Platform > Tools admin tab for maintenance and CLI-adjacent operations

The admin dashboard you inspect after running the demo seeder documented on this page

includes/Core/Plugin.php
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-fixtures does not exist in a packaged install. It lives in dev/, which is not on bin/build-release.sh’s runtime allowlist, so the file is absent from the shipped zip and the is_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.

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.

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.

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.

Terminal window
# Populate a demo community
wp buddynext demo seed
# See what is installed
wp buddynext demo status
# Remove everything the seeder created
wp buddynext demo cleanup

Sample seed output:

Seeded 24 members, 6 spaces, 80 posts, 9 profile fields.

Sample status output:

Members: 24
Spaces: 6
Posts: 80
Profile fields: 9

Note: The exact counts depend on the bundled dataset; the numbers above are illustrative. Re-running seed without first running cleanup is a no-op that warns - it never duplicates the dataset.

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.

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 --json for its own output formatter and would reject it.

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:

  1. Snapshots the current setting state.
  2. Flips the setting OFF and asserts the REST surface’s behavior changes - the disabled error code appears.
  3. Flips the setting ON and asserts the disabled error code is gone.
  4. 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 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.

Terminal window
# Full functional certification (contract + boot); exits 1 on any failure
wp buddynext cert
# Only the dead-toggle behaviour-flip check
wp buddynext cert contract
# Only the REST boot smoke
wp buddynext cert boot
# Machine-readable ledger for CI / MCP
wp buddynext cert --porcelain

Sample 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)

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.
Terminal window
# See what it would do first.
wp buddynext repair-space-owners --dry-run
# Then let it write.
wp buddynext repair-space-owners

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.

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
Terminal window
wp buddynext qa-fixtures seed # edge cases (the default)
wp buddynext qa-fixtures seed --profile=community # a populated community
wp buddynext qa-fixtures seed --profile=scale # big-site scale data
wp buddynext qa-fixtures seed --profile=all # everything
wp buddynext qa-fixtures status
wp buddynext qa-fixtures cleanup
  • demo and cert declare @when after_wp_load, so WordPress is fully loaded before they run - they have access to services, settings, and the REST router.
  • cert writes a ledger as a side effect of every run, so CI and the MCP can read the last result without re-running the gate.
  • demo and cert are Free commands. Pro registers one WP-CLI command of its own - wp buddynext-pro cert (\BuddyNextPro\Cert\CertCommand, added in the Pro Plugin::init()) - the same functional-certification harness scoped to Pro’s gated features. It takes the same optional contract / boot positional and --porcelain flag. Free’s cert oracle covers gated features in Free.

See also the Cron and Async Jobs page for the scheduled-job surface these tools run alongside.