diff --git a/includes/functions.php b/includes/functions.php
index 02c97785edda8df180ed4e290b915aad8968c5a6..7a3fce4a8b2c1b989a486b8bfe3f59d451dad2e8 100644
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -3,13 +3,13 @@
 namespace Automattic\WP\WP_CLI_Cron_Control_Offload;
 
 /**
- * Check if subcommand is allowed
+ * Check if command is allowed
  *
- * @param string $subcommand
+ * @param string $command
  * @return bool
  */
-function is_subcommand_allowed( $subcommand ) {
-	return in_array( $subcommand, get_command_whitelist(), true ) && ! in_array( $subcommand, get_command_blacklist(), true );
+function is_command_allowed( $command ) {
+	return in_array( $command, get_command_whitelist(), true ) && ! in_array( $command, get_command_blacklist(), true );
 }
 
 /**
@@ -23,6 +23,8 @@ function get_command_whitelist() {
 		'cache',
 		'cap',
 		'comment',
+		'cron-control',
+		'cron-control-fixers',
 		'media',
 		'menu',
 		'network',
@@ -80,7 +82,7 @@ function schedule_cli_command( $args ) {
 		return $event_args;
 	}
 
-	$scheduled = wp_schedule_single_event( strtotime( '+30 seconds' ), ACTION, $event_args );
+	$scheduled = wp_schedule_single_event( strtotime( '+30 seconds' ), ACTION, array( 'command' => $event_args ) );
 
 	return false !== $scheduled;
 }
@@ -88,21 +90,33 @@ function schedule_cli_command( $args ) {
 /**
  * Validate WP-CLI command to be scheduled
  *
- * @param array $args
+ * @param string $args
  * @return array|\WP_Error
  */
 function validate_args( $args ) {
-	$validated_args = array();
+	// Strip `wp` if included
+	if ( 0 === stripos( $args, 'wp' ) ) {
+		$args = trim( substr( $args, 2 ) );
+	}
+
+	// Block disallowed commands
+	$command = explode( ' ', $args );
+	$command = array_shift( $command );
+	if ( ! is_command_allowed( $command ) ) {
+		return new \WP_Error( "$command not allowed" );
+	}
 
-	// TODO: validate
-	// TODO: strip leading "wp"
-	// TODO: check first positional argument against `is_command_allowed()`
+	// Don't worry about the user WP-CLI runs as
+	if ( false === stripos( $args, '--allow-root' ) ) {
+		$args .= ' --allow-root';
+	}
 
-	$validated_args['command'] = $args;
+	// TODO: validate further
 
-	if ( empty( $validated_args ) ) {
-		return new \WP_Error( 'Arguments could not be parsed for validation.' );
+	// Nothing to run
+	if ( empty( $args ) ) {
+		return new \WP_Error( 'Invalid command provided' );
 	}
 
-	return $validated_args;
+	return $args;
 }
diff --git a/includes/run.php b/includes/run.php
index 95d6ca4ad3d1c19b67fffa2d2574edb1c4226e52..a4af0be7e424d4da9c8b04e19c669b6b8451a884 100644
--- a/includes/run.php
+++ b/includes/run.php
@@ -5,17 +5,40 @@ namespace Automattic\WP\WP_CLI_Cron_Control_Offload;
 /**
  * Intended for non-interactive use, so all output ends up in the error log
  *
- * @param array $args
+ * @param string $command
  * @return null
  */
-function run_event( $args ) {
+function run_event( $command ) {
 	if ( ! defined( 'WP_CLI' ) || ! \WP_CLI ) {
 		// TODO: reschedule at least once or twice
-		trigger_error( 'Attempted to run event without WP-CLI loaded. ' . var_export( $args, true ), E_USER_WARNING );
-		return false;
+		trigger_error( 'Attempted to run event without WP-CLI loaded. (' . var_export( $command, true ) . ')', E_USER_WARNING );
+		return;
 	}
 
-	// TODO: run event, sending output to error log
-	trigger_error( var_export( $args, true ), E_USER_NOTICE );
+	if ( ! validate_args( $command ) ) {
+		trigger_error( 'Attempted to run blocked WP-CLI command. (' . var_export( $command, true ) . ')', E_USER_WARNING );
+		return;
+	}
+
+	// TODO: time event execution
+
+	$output = \WP_CLI::runcommand( $command, array(
+		'return' => 'all',
+	) );
+
+	// Command failed
+	if ( ! is_object( $output ) || is_wp_error( $output ) ) {
+		trigger_error( 'WP-CLI command failed. (' . var_export( $command, true ) . ')', E_USER_WARNING );
+		trigger_error( var_export( $output, true ), E_USER_WARNING );
+		return;
+	}
+
+	// On success, reformat response for logging
+	$output->command = $command;
+
+	$output = var_export( $output, true );
+	$output = ACTION . ":\n{$output}";
+
+	error_log( $output );
 }
 add_action( ACTION, __NAMESPACE__ . '\run_event' );