Filter my args by the post 1st letter

To restrict to letter X dynamically, the following should work. It depends upon the fact that WP_Query will let ad hoc parameters pass through. That lets you send your own data to the filters. I do not know if this is intentional behavior so caveat emptor, but it is very useful behavior.

Simply send your letter of choice via the substring_where parameter and let the filters work. There are two versions, one using SUBSTRING as you were trying to do, and one using LIKE. I don’t know which is faster, though they seem very close.

I also used $wpdb->prepare but that may not be necessary. It depends on where you data is coming from.

$args = array (
  'post_type' => 'post',
  'ignore_sticky_posts' => true,
  'substring_where' => 't',
);

function restrict_by_first_letter( $where, $qry ) {
  global $wpdb;
  $sub = $qry->get('substring_where');
  if (!empty($sub)) {
    $where .= $wpdb->prepare(
      " AND SUBSTRING( {$wpdb->posts}.post_title, 1, 1 ) = %s ",
      $sub
    );

//  $where .= $wpdb->prepare(
//    " AND {$wpdb->posts}.post_title LIKE %s ",
//    $sub.'%'
//  );
  }
  return $where;
}
add_filter( 'posts_where' , 'restrict_by_first_letter', 1 , 2 );

$results = new WP_Query( $args );

var_dump($results->request); // debug
var_dump(wp_list_pluck($results->posts,'post_title')); // debug