Contents

WP-CLI - Plugixa Activity Log

One command, wp activity-log, that reads the log and manages it from a terminal. It is part of the free plugin.

wp activity-log list --min_severity=high --per-page=20
wp activity-log tail --group=authentication
wp activity-log disable 1000 1001
wp activity-log prune --dry-run
wp activity-log import wsal --dry-run

Three things to know first

Times are UTC. The log stores every event in UTC and the terminal prints them as stored, whatever the site’s time zone is. The admin screens convert to local time; the CLI does not. The one exception runs the other way: --date_from and --date_to are read in the site’s time zone, exactly as the screen’s date filter is.

Every change made from the CLI is logged, with source “cli”. Switching an event off, switching a monitor, changing a setting and pruning all go through the same code the admin screens use, so they are checked the same way and leave the same entry in the log. The entry’s details carry source: cli, and it has no IP address, because a terminal has none. It has no user either, unless you run the command with WP-CLI’s own --user= flag.

The CLI sees the whole network. On multisite, somebody with a shell can read the database anyway, so the command is not confined to one site. Narrow it on purpose with --site_id=<id>.

The subcommands

Subcommand Does
list List events, newest first
get <id> Show one event in full
tail Print new events as they happen
stats Totals for a period
events The event catalogue, and whether each event is recorded
enable <code>... Start recording events
disable <code>... Stop recording events
monitors List the monitors and whether each runs
monitor <id> Switch a monitor on or off
prune Apply the retention settings now
settings get Read one setting, or all of them
settings set Change one setting
import wsal Import history from WP Activity Log

list

List events, newest first.

wp activity-log list
wp activity-log list --min_severity=high --per-page=20
wp activity-log list --user_login=alex --date_from=2026-10-01 --format=csv
wp activity-log list --search="plugin activated" --fields=id,time,message
Flag Does
--per-page=<n> How many. Default 50, at most 200
--before-id=<id> Only events older than this id: the next page
--format=<format> table (default), json, csv, yaml, ids or count
--fields=<fields> Comma-separated columns. Default id,time,severity,code,user,ip,message
--<filter>=<value> Any filter below

The filters are the same ones the REST API accepts, with the same names:

Filter Matches
--severity Exact severities, comma separated: informational, low, medium, high, critical
--min_severity At least this severe
--event_code Event codes, comma separated
--group, --module An event group such as authentication, or the module that owns the events
--user_id, --user_login, --user_role Who acted. --user_login also matches the name typed at a failed sign-in
--ip An exact address
--object_type, --object_id, --action What it was about, and the verb
--search Free text over the message, the item and the user
--date_from, --date_to Y-m-d or ISO 8601, read in the site’s time zone
--site_id One site of a network

Note the spelling. The paging flags use hyphens (--per-page, --before-id) and the filters use underscores (--min_severity, --user_login).

A filter value the plugin does not understand is ignored, not an error, so check the result if a filter seems to have done nothing.

To page through a large log, pass the last id you saw:

wp activity-log list --per-page=200 --format=ids
wp activity-log list --per-page=200 --before-id=48211

get

Show one event in full, including everything that was captured.

wp activity-log get 48211
wp activity-log get 48211 --format=yaml
Flag Does
--format=<format> json (default) or yaml

An id that does not exist is an error: Event 48211 does not exist.

tail

Print new events as they happen, until you press Ctrl-C.

wp activity-log tail
wp activity-log tail --group=authentication
wp activity-log tail --min_severity=high --interval=5
Flag Does
--interval=<seconds> How often to look. Default 2, at least 1
--<filter>=<value> Any filter list accepts

It starts from the newest event that matches and prints only what arrives afterwards, oldest first, one line each: id, time, severity, code, user, address and message.

stats

Totals for a period.

wp activity-log stats
wp activity-log stats --days=7
wp activity-log stats --days=90 --format=json
Flag Does
--days=<days> The window. Default 30, at most 365
--format=<format> table (default) or json

The table prints the totals. --format=json returns everything the Dashboard draws: totals, events per day, counts by severity, the most active users and addresses, and the recent high-severity events.

events

The event catalogue: every event the plugin can record, and whether it is on.

wp activity-log events
wp activity-log events --format=csv > events.csv
Flag Does
--format=<format> table (default), json, csv or yaml

The columns are code, group, severity, enabled, default and message. default shows whether the event is on out of the box, so a row where enabled and default disagree is one somebody changed.

enable and disable

Start or stop recording one or more events, by code.

wp activity-log disable 1000 1001
wp activity-log enable 1000

Both take one or more event codes and no flags.

Disabling stops new entries only. What is already in the log is kept.

An unknown code is an error, and nothing is changed when one is: fix the list and run it again. The change is recorded as event 9000, Activity Log settings were changed.

monitors and monitor

monitors lists the monitors and whether each runs.

wp activity-log monitors
wp activity-log monitors --format=json
Flag Does
--format=<format> table (default), json, csv or yaml

The columns are id, label, enabled and core. A core monitor cannot be switched off.

monitor switches one, by the id from that list.

wp activity-log monitor php_errors --enable
wp activity-log monitor not_found --disable
Flag Does
--enable Switch it on
--disable Switch it off

Pass exactly one of the two. Neither, or both, is an error.

Switching a monitor off also cancels its scheduled jobs. The change is recorded as event 9002. See Monitors.

prune

Apply the retention settings now, instead of waiting for the daily job.

wp activity-log prune --dry-run
wp activity-log prune
Flag Does
--dry-run Only say how many events would be removed

Run the dry run before shortening the retention period on a log you care about. It counts and writes nothing.

A real prune that removes anything is recorded as event 9001. See Retention.

settings get and settings set

Read or change a setting.

wp activity-log settings get
wp activity-log settings get retention_days
wp activity-log settings set retention_days 30
wp activity-log settings set view_roles '["editor"]'
wp activity-log settings set notify_enabled true
Form Does
settings get Print every setting, as JSON
settings get <key> Print one setting
settings set <key> <value> Change one setting

A value that parses as JSON is used as JSON. That is how lists and switches are set: '["editor"]', true, 30. Anything else is a plain string. Quote a list so the shell does not interpret the brackets.

An unknown key is an error, and the message lists the keys that exist. A typo in a terminal deserves to be told, not silently dropped.

The value goes through the same checks as the Settings screen, so what is stored may differ from what you typed. settings set records_per_page 5000 stores 200, the maximum, and the command prints the value as stored:

Success: records_per_page = 200

The setting names are keys such as retention_days, retention_max_rows, view_roles, excluded_ips, privacy_ip_mode and trusted_proxy_header. settings get with no key is the complete list for your build, and every key is listed with its default in the Developer reference. What each one does is on the Settings page.

import

Import the history of another activity log plugin. The only source is wsal, WP Activity Log.

wp activity-log import wsal --dry-run
wp activity-log import wsal --from=2025-01-01
wp activity-log import wsal --skip-unmapped
Flag Does
--dry-run Only count what would be imported
--from=<date> Only events from this day on (YYYY-MM-DD)
--skip-unmapped Leave out events this plugin has no equivalent for, instead of keeping them as generic imported events

Without --dry-run the command does the whole import itself, in the terminal, and does not hand it to the background job. Imported events keep their original dates and send no notifications, the import resumes where it stopped, and it never imports an event twice. See Importing from WP Activity Log.

Where to run it

cd /path/to/wordpress
wp activity-log list

On a multisite, add --url= for the site the plugin is active on. A command that fails prints the reason and exits with code 1, so it can be used in a script:

wp activity-log list --min_severity=critical --date_from=$(date +%F) --format=count

Troubleshooting

Symptom Usual cause
“‘activity-log’ is not a registered wp command” The plugin is not active on the site WP-CLI is pointed at, or --url= is missing on multisite.
Times are hours away from what the screen shows The CLI prints UTC. The screen converts to local time.
--per_page or --min-severity did nothing Paging flags use hyphens, filters use underscores.
A filter seems to be ignored Its value was not understood, and an unknown value is dropped.
“Pass exactly one of –enable or –disable.” monitor needs one of the two flags.
“That monitor cannot be switched off.” It is a core monitor.
“Event … does not exist.” from disable One code is unknown, and nothing was changed.
A setting was stored with a different value It was pulled into its allowed range, or an invalid entry was dropped.
prune removed fewer events than the dry run said One run works within a time budget and books a follow-up. Run it again.

What to do next

  • The same data over HTTP: REST API.
  • What each event code means: Events.
  • Check the scheduled jobs: Health.

Quick Links