diff --git a/includes/class-wp-cli.php b/includes/class-wp-cli.php
new file mode 100644
index 0000000000000000000000000000000000000000..265566a919fde308a21d8eb897b72b9deb6baabc
--- /dev/null
+++ b/includes/class-wp-cli.php
@@ -0,0 +1,66 @@
+<?php
+
+WP_CLI::add_command( 'syndication', 'Syndication_CLI_Command' );
+
+class Syndication_CLI_Command extends WP_CLI_Command {
+
+	function pull_site( $args, $assoc_args ) {
+		$assoc_args = wp_parse_args( $assoc_args, array(
+			'site_id' => 0,
+		) );
+
+		$site_id = intval( $assoc_args['site_id'] );
+		$site = get_post( $site_id );
+var_dump( $site_id, $site );
+		if ( ! $site || 'syn_site' !== $site->post_type )
+			WP_CLI::error( "Please select a valid site." );
+
+		// enable verbosity
+		$this->_make_em_talk_pull();
+
+		$this->_get_syndication_server()->pull_content( array( $site ) );
+	}
+
+	function pull_sitegroup( $args, $assoc_args ) {
+		$assoc_args = wp_parse_args( $assoc_args, array(
+			'sitegroup' => '',
+		) );
+
+		$sitegroup = sanitize_key( $assoc_args['sitegroup'] );
+
+		if ( empty( $sitegroup ) )
+			WP_CLI::error( "Please specify a valid sitegroup" );
+
+		$server = $this->_get_syndication_server();
+		$sites = $server->get_sites_by_sitegroup( $sitegroup );
+
+		// enable verbosity
+		$this->_make_em_talk_pull();
+
+		// do it, to it
+		$server->pull_content( $sites );
+	}
+
+	function _make_em_talk_pull() {
+		// output when a post is new or updated
+		add_filter( 'syn_pre_pull_posts', function( $posts, $site, $client ) {
+			WP_CLI::line( sprintf( 'Processing feed %s (%d)', $site->post_title, $site->ID ) );
+			WP_CLI::line( sprintf( '-- found %s posts', count( $posts ) ) );
+
+			return $posts;
+		}, 10, 3 );
+
+		add_action( 'syn_post_pull_new_post', function( $result, $post, $site, $transport_type, $client ) {
+			WP_CLI::line( sprintf( '-- New post #%d (%s)', $result, $post['post_guid'] ) );
+		}, 10, 5 );
+
+		add_action( 'syn_post_pull_edit_post', function( $result, $post, $site, $transport_type, $client ) {
+			WP_CLI::line( sprintf( '-- Updated post #%d (%s)', $result, $post['post_guid'] ) );
+		}, 10, 5 );
+	}
+
+	function _get_syndication_server() {
+		global $push_syndication_server;
+		return $push_syndication_server;
+	}
+}
diff --git a/push-syndication.php b/push-syndication.php
index 82a30828a72976d6df59890d8e02c3754ea36bd3..72c1313423439be7364af391ff666a1eda27d53a 100644
--- a/push-syndication.php
+++ b/push-syndication.php
@@ -21,5 +21,8 @@ if( apply_filters( 'syn_use_async_jobs', false ) )
 if ( !defined( 'PUSH_SYNDICATION_ENVIRONMENT' ) )
     define( 'PUSH_SYNDICATION_ENVIRONMENT', 'WP' );
 
+if ( defined( 'WP_CLI' ) && WP_CLI )
+	require_once( dirname( __FILE__ ) . '/includes/class-wp-cli.php' );
+
 $push_syndication_server_class = PUSH_SYNDICATION_ENVIRONMENT . '_Push_Syndication_Server';
 $push_syndication_server = new $push_syndication_server_class();