BetterShield
Appearance
Security auditHardeningSettings

WordPress security from the command line: WP-CLI commands

· · Updated · 12 min read

To manage WordPress security from the command line, use the fifteen wp bettershield commands that BetterShield adds to WP-CLI. They run an audit, list findings, preview and undo hardening fixes, read the activity log, release lockouts and recover access from a terminal. They use the same code as the dashboard, so the terminal and the screens always agree. This guide shows what each command is for, the pattern they all follow, and the settings we recommend.

It builds on the hardening guide, whose fixes the harden command applies, and on the WordPress security checklist, whose checks the audit command runs.

Quick summary

  • BetterShield adds fifteen wp bettershield commands: audit, findings, harden, activity, agents, verify_log, recover, lockdown, lockouts, blocklist, integrity, alerts, settings, vulnerabilities and diagnostics.
  • Reading needs no user. A command that changes the site needs --user=<login>, naming an account that can manage BetterShield, and the change is recorded against it.
  • Changes made this way are logged as coming through WP-CLI, in the same activity log as changes made in the dashboard.
  • wp bettershield recover never asks for a user, because it exists for the day nobody can sign in.
  • audit can exit non-zero when the score or a finding crosses a line you set, which makes it usable as a gate in a script.

Why use the terminal at all

The dashboard is the right place to learn what BetterShield does. The terminal is the right place once you manage more than one site, want a record in a script, or cannot reach the dashboard. WP-CLI is WordPress’s own command-line interface, and commands from plugins appear beside the core ones. Nothing here needs a special setup beyond WP-CLI itself.

Because the commands share code with the dashboard, there is no second set of rules to learn. A fix applied by wp bettershield harden runs the same code as one applied in the dashboard, and the activity log notes that it came through WP-CLI.

The pattern every command follows

Two rules cover almost everything.

  1. Reading is free. audit, findings, activity, agents, verify_log and the list forms of lockouts and blocklist change nothing and need no user.
  2. Changing needs a named person. Add --user=<login> with an account that can manage BetterShield. The change is recorded against that account, so the log says who did it even though no browser was involved.
wp bettershield harden xmlrpc --undo --user=admin

Most list commands also take --format=, with table, json or csv depending on the command, so the output can go straight into a spreadsheet or another tool. Times print in the site’s time zone, and an option a command does not use is refused rather than ignored.

The commands, grouped by job

JobCommands
See where the site standsaudit, findings
Change a settingharden, settings
Read what happenedactivity, agents, verify_log
Get back in or hold the linerecover, lockdown
Manage who is paused or refusedlockouts, blocklist
Check files and advisoriesintegrity, vulnerabilities
Manage who gets alert emailalerts
Ask for helpdiagnostics

Audit and findings

wp bettershield audit runs the read-only audit and prints the score, the grade and the open findings by severity. Two options turn it into a gate:

  • --fail-under=<score> exits non-zero when the score is below a whole number from 0 to 100.
  • --fail-on=<severity> exits non-zero when an open finding is at that severity or worse: critical, high, medium or low.
wp bettershield audit --fail-under=80 --fail-on=high

The score changed in 1.1.3: it is now 60 points for setup essentials and 40 for site health, and it is capped at 74 while a critical finding is open. Your score will move after you update, so recheck any --fail-under threshold in a deploy script before you rely on it.

--format= takes summary (the default) or json. wp bettershield findings lists findings from the last audit with the ID of the fix where there is one. --status= takes open (the default), snoozed, suppressed, fixed or all.

wp bettershield findings --status=snoozed

What the audit looks at, and what it misses, is covered in the security audit guide.

Hardening

wp bettershield harden lists the hardening fixes, or previews, applies or undoes one. Leave out the fix’s ID and it lists every fix with its ID and state. Three options matter most:

  • --dry-run describes what applying would do and changes nothing. It cannot be combined with --undo.
  • --undo reverts the fix.
  • --force applies a sign-in fix even though the recovery check failed. It is recorded in the activity log.
wp bettershield harden login_url --slug=side-door --user=admin
wp bettershield harden xmlrpc --undo --user=admin

The recovery check is there for a reason: BetterShield makes sure a recovery link or printed code works before a change to how people sign in. We recommend leaving --force alone unless you have another way back in.

Activity and agents

wp bettershield activity shows the activity log, newest first. It takes --limit=<number> (at most 500, default 40), --area= (access, exposure, server, configuration, extensions or plugin), --search=, --actor=, a --from= and --to= day range, and --format=. On a multisite network --sites= takes site IDs or all; for the network screens that sit beside it, see WordPress multisite security. In CSV format it exports every matching row:

wp bettershield activity --from=2026-08-01 --to=2026-08-15 --format=csv > august.csv

wp bettershield agents shows every ability call on the site from any plugin, and needs WordPress 7.1. --outcome=permission_denied is a quick way to see what an assistant was refused. wp bettershield verify_log checks the activity log against its daily seals and exits non-zero if a sealed day was altered, removed or could not be read.

Recovery and lockdown

wp bettershield recover turns on safe mode: BetterShield’s protections pause and the standard sign-in page answers again. No setting is lost, and rules BetterShield wrote to .htaccess and index files stay in place. --hours= sets how long, from 1 to 24 (the default is 1), --end ends it early, and --new-link also issues a fresh recovery link, printed once, which makes the previous one stop working.

wp bettershield recover --hours=4 --new-link

wp bettershield lockdown shows, turns on or lifts the site lockdown. status needs no user, while on and off need --user=<login>. From a terminal there is no browser session to keep, so on signs out every dashboard session, including your own. The recovery link and safe mode still outrank it. If you are already locked out, start with getting back in.

Lockouts and the blocklist

wp bettershield lockouts lists lockouts on the sign-in form and the public forms, or releases them. Releasing needs --user=<login> and is recorded in the activity log. --surface= limits it to signin, comment, reset or register, and --active shows only the lockouts running now.

wp bettershield lockouts list --active
wp bettershield lockouts release --all --surface=signin --user=admin

wp bettershield blocklist lists Never allowed to sign in, or adds or removes an entry with the same checks as Protection › Login & Access. An entry can name a network with --range=, part of a user agent with --ua= (at least four characters), a username with --username=, or a combination, and all of them have to match.

wp bettershield blocklist add --range=203.0.113.0/24 --note="Scanner" --user=admin

The thinking behind both lists is in the allowlist and blocklist guide.

Files, settings and the rest

wp bettershield integrity compares core, directory-plugin and supported WPDeveloper paid-plugin files against the published copies. status and scan need no user; restore puts the published copy back, sends the current file to quarantine and prints an undo token. --fail-on-changes makes it exit non-zero when any file differs. The list of open changes comes a page at a time: --change= (modified, added, removed, unreadable or package_mismatch) and --location= (core, plugin, theme, muplugin, dropin, config, unlisted or extra) narrow it, a cut table prints the command for the next page with --cursor=, and --format=csv exports every match.

wp bettershield integrity --change=added --location=core
wp bettershield integrity --format=csv > changes.csv

See the file integrity check for what the screen shows.

wp bettershield settings export posture.json writes BetterShield’s settings as JSON. import only shows its plan until you add --apply, which is what makes it safe to use for rolling one site’s setup out to the next:

wp bettershield settings import posture.json --apply --user=admin

wp bettershield vulnerabilities shows the optional feed’s state; check requests a refresh after consent. A missing or failed result is never reported as clean. See Vulnerability checks.

Manage alerts and host deployments

Free 1.1.5 adds wp bettershield alerts for the people who get security email. Listing recipients needs no user; every change needs --user=<login>. recipients list takes --format= with table, json or csv and shows what each address chose to receive.

wp bettershield alerts recipients list --format=json
wp bettershield alerts recipients add security@example.com --user=admin
wp bettershield alerts recipients remove security@example.com --user=admin
wp bettershield alerts recipients reset --user=admin
wp bettershield alerts mute --user=admin
wp bettershield alerts unmute --user=admin

recipients reset goes back to the site administration email as the fallback. Adding a recipient or unmuting does not turn on the instant-alert or weekly-summary switch; on a new install both stay off until you turn them on in Quick Setup or Settings. The longer story is in the email alerts guide and Alert recipients.

A host that sends its own routine notices can take them over:

wp bettershield alerts host-managed on --user=admin
wp bettershield alerts host-managed off --user=admin

Host-managed mode holds routine events for the weekly summary. While instant alerts are enabled, a new administrator, a role raised to administrator, the trap password and a changed code file still email at once. It does not enable either email switch. See Host-managed alerts.

Two integrity actions are for deployments that happen outside WordPress’s updater. Neither one checks who wrote the code or whether it is safe, so confirm the change against your deployment record first.

wp bettershield integrity record-update --slug=your-plugin --version=1.2.3 --user=admin
wp bettershield integrity expect-file --file=.htaccess --user=admin

record-update records a known plugin or theme update (add --type=theme for a theme); the component needs an earlier recorded copy and a version that actually changed, and changes that are already open stay open. expect-file accepts one reviewed host-written file as its expected state and prints an undo token. For a paid plugin, integrity expect previews a group of changes for one version, and --yes accepts it for that version only:

wp bettershield integrity expect --slug=your-paid-plugin --version=1.2.3
wp bettershield integrity expect --slug=your-paid-plugin --version=1.2.3 --yes --user=admin

wp bettershield integrity undo --token=<token> --user=admin brings an accepted change back for review. See Record host file changes and Expected file changes.

What it can break, and how to undo

  • A hardening fix you did not mean to apply. Preview with --dry-run first. Undo with the same command plus --undo.
  • A sign-in change that locks people out. BetterShield runs its recovery check before a sign-in change. --force skips that protection, so use it deliberately. wp bettershield recover is the way back.
  • A lockdown that ends your own session. lockdown on from a terminal signs out every dashboard session, yours included. Run lockdown off --user=<login> to lift it.
  • A file change accepted too soon. record-update, expect-file and expect --yes can hide that exact change. Keep the printed undo token; a later edit to the file is still reported.
  • A settings import that changes more than you expected. Run it without --apply first and read the plan. Blocklist changes can also be reversed under Settings history on Settings › General.

Check it is working

  • wp bettershield audit prints a score and grade.
  • After a change, wp bettershield activity --limit=5 shows the entry, recorded as coming through WP-CLI and attributed to the account you passed.
  • wp bettershield harden with no ID lists each fix and its state.
  • wp bettershield verify_log exits cleanly when the activity log matches its seals.

We recommend using the terminal for reading by default and for changes you can preview.

  • Gate a deployment: run wp bettershield audit --fail-under=80 --fail-on=high after a deploy, with a threshold that suits the site.
  • Always dry-run first: harden --dry-run and an import without --apply both show a plan and change nothing.
  • Name a real person for --user: the log is only as useful as the account it points to.
  • Keep a settings export: settings export before a batch of changes is a cheap way back.
  • Looking after several sites: a script covers each one, and the free hub lists every site’s score in one place. Manage security across many WordPress sites from one hub walks through it.

BetterShield Ultra adds wp bettershield-ultra policy, grants, channels, edge and report, which only read and so need no --user. The free commands above need nothing else.

Frequently asked questions

Do I need a user for every WP-CLI command?

No. Reading commands such as audit, findings, activity and agents need no user. A command that changes the site needs --user=<login>, and recover never asks for one.

Can I run a WordPress security audit from the command line?

Yes. wp bettershield audit runs the read-only audit and prints the score, grade and open findings. Add --format=json for machine-readable output.

How do I make a script fail when the score is too low?

Use --fail-under=<score> with a whole number from 0 to 100, or --fail-on=<severity> to fail on an open finding at that severity or worse. Both make the command exit non-zero.

Are changes made in WP-CLI recorded?

Yes. They go into the activity log and are logged as coming through WP-CLI, attributed to the account you named with --user.

What if I am locked out and cannot use the dashboard?

Run wp bettershield recover. It turns on safe mode so the standard sign-in page answers again, and it needs no user.

How do I stop BetterShield flagging files my host deployed?

Record the deployment instead of ignoring the report. integrity record-update records a known plugin or theme update made outside WordPress’s updater, and integrity expect-file accepts one reviewed file your host wrote. Both need --user=<login>, and both leave other open changes for you to review.

Conclusion

The commands are the dashboard’s own code with a terminal in front: read freely, change with a named user, preview before you apply, and keep recover in your back pocket. BetterShield is free on WordPress.org; every option is listed in the WP-CLI commands reference, and the fixes behind harden are explained in Hardening.

Close the open doors today

Install the free plugin. The first audit runs when you activate it, and all but one of the fixes wait for your choice.

Requires WordPress 6.7 or newer and PHP 8.0 or newer.

Get BetterShield