diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2295,11 +2295,15 @@
     'PhabricatorProjectIcon' => 'applications/project/icon/PhabricatorProjectIcon.php',
     'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php',
     'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
+    'PhabricatorProjectLogicDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicDatasource.php',
+    'PhabricatorProjectLogicalAndDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalAndDatasource.php',
+    'PhabricatorProjectLogicalOrNotDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php',
     'PhabricatorProjectMemberOfProjectEdgeType' => 'applications/project/edge/PhabricatorProjectMemberOfProjectEdgeType.php',
     'PhabricatorProjectMembersDatasource' => 'applications/project/typeahead/PhabricatorProjectMembersDatasource.php',
     'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php',
     'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php',
     'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php',
+    'PhabricatorProjectNoProjectsDatasource' => 'applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php',
     'PhabricatorProjectObjectHasProjectEdgeType' => 'applications/project/edge/PhabricatorProjectObjectHasProjectEdgeType.php',
     'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php',
     'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php',
@@ -5671,11 +5675,15 @@
     'PhabricatorProjectFeedController' => 'PhabricatorProjectController',
     'PhabricatorProjectIcon' => 'Phobject',
     'PhabricatorProjectListController' => 'PhabricatorProjectController',
+    'PhabricatorProjectLogicDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
+    'PhabricatorProjectLogicalAndDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
+    'PhabricatorProjectLogicalOrNotDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
     'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType',
     'PhabricatorProjectMembersDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
     'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController',
     'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController',
     'PhabricatorProjectMoveController' => 'PhabricatorProjectController',
+    'PhabricatorProjectNoProjectsDatasource' => 'PhabricatorTypeaheadDatasource',
     'PhabricatorProjectObjectHasProjectEdgeType' => 'PhabricatorEdgeType',
     'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
     'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicDatasource.php
@@ -0,0 +1,22 @@
+<?php
+
+final class PhabricatorProjectLogicDatasource
+  extends PhabricatorTypeaheadCompositeDatasource {
+
+  public function getPlaceholderText() {
+    return pht('Type a project name or selector...');
+  }
+
+  public function getDatasourceApplicationClass() {
+    return 'PhabricatorProjectApplication';
+  }
+
+  public function getComponentDatasources() {
+    return array(
+      new PhabricatorProjectNoProjectsDatasource(),
+      new PhabricatorProjectLogicalAndDatasource(),
+      new PhabricatorProjectLogicalOrNotDatasource(),
+    );
+  }
+
+}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalAndDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalAndDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalAndDatasource.php
@@ -0,0 +1,32 @@
+<?php
+
+final class PhabricatorProjectLogicalAndDatasource
+  extends PhabricatorTypeaheadCompositeDatasource {
+
+  public function getPlaceholderText() {
+    return pht('Type a project name...');
+  }
+
+  public function getDatasourceApplicationClass() {
+    return 'PhabricatorProjectApplication';
+  }
+
+  public function getComponentDatasources() {
+    return array(
+      new PhabricatorProjectDatasource(),
+    );
+  }
+
+  public function evaluateTokens(array $tokens) {
+    $results = parent::evaluateTokens($tokens);
+
+    foreach ($results as $key => $result) {
+      $results[$key] = new PhabricatorQueryConstraint(
+        PhabricatorQueryConstraint::OPERATOR_AND,
+        $result);
+    }
+
+    return $results;
+  }
+
+}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php
@@ -0,0 +1,115 @@
+<?php
+
+final class PhabricatorProjectLogicalOrNotDatasource
+  extends PhabricatorTypeaheadCompositeDatasource {
+
+  public function getPlaceholderText() {
+    return pht('Type any(<project>) or not(<project>)...');
+  }
+
+  public function getDatasourceApplicationClass() {
+    return 'PhabricatorProjectApplication';
+  }
+
+  public function getComponentDatasources() {
+    return array(
+      new PhabricatorProjectDatasource(),
+    );
+  }
+
+  public function getDatasourceFunctions() {
+    return array(
+      'any' => array(
+        'name' => pht('Find results in any of several projects.'),
+      ),
+      'not' => array(
+        'name' => pht('Find results not in specific projects.'),
+      ),
+    );
+  }
+
+  protected function didLoadResults(array $results) {
+    $function = $this->getCurrentFunction();
+    $return_any = ($function !== 'not');
+    $return_not = ($function !== 'any');
+
+    $return = array();
+    foreach ($results as $result) {
+      $result
+        ->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
+        ->setIcon('fa-asterisk');
+
+      if ($return_any) {
+        $return[] = id(clone $result)
+          ->setPHID('any('.$result->getPHID().')')
+          ->setDisplayName(pht('In Any: %s', $result->getDisplayName()))
+          ->setName($result->getName().' any');
+      }
+
+      if ($return_not) {
+        $return[] = id(clone $result)
+          ->setPHID('not('.$result->getPHID().')')
+          ->setDisplayName(pht('Not In: %s', $result->getDisplayName()))
+          ->setName($result->getName().' not');
+      }
+    }
+
+    return $return;
+  }
+
+  protected function evaluateFunction($function, array $argv_list) {
+    $phids = array();
+    foreach ($argv_list as $argv) {
+      $phids[] = head($argv);
+    }
+
+    $operator = array(
+      'any' => PhabricatorQueryConstraint::OPERATOR_OR,
+      'not' => PhabricatorQueryConstraint::OPERATOR_NOT,
+    );
+
+    $results = array();
+    foreach ($phids as $phid) {
+      $results[] = new PhabricatorQueryConstraint(
+        $operator[$function],
+        $phid);
+    }
+
+    return $phids;
+  }
+
+  public function renderFunctionTokens($function, array $argv_list) {
+    $phids = array();
+    foreach ($argv_list as $argv) {
+      $phids[] = head($argv);
+    }
+
+    $tokens = $this->renderTokens($phids);
+    foreach ($tokens as $token) {
+      if ($token->isInvalid()) {
+        if ($function == 'any') {
+          $token->setValue(pht('In Any: Invalid Project'));
+        } else {
+          $token->setValue(pht('Not In: Invalid Project'));
+        }
+      } else {
+        $token
+          ->setIcon('fa-asterisk')
+          ->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION);
+
+        if ($function == 'any') {
+          $token
+            ->setKey('any('.$token->getKey().')')
+            ->setValue(pht('In Any: %s', $token->getValue()));
+        } else {
+          $token
+            ->setKey('not('.$token->getKey().')')
+            ->setValue(pht('Not In: %s', $token->getValue()));
+        }
+      }
+    }
+
+    return $tokens;
+  }
+
+}
diff --git a/src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php b/src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php
@@ -0,0 +1,62 @@
+<?php
+
+final class PhabricatorProjectNoProjectsDatasource
+  extends PhabricatorTypeaheadDatasource {
+
+  public function getPlaceholderText() {
+    return pht('Type "not in any projects"...');
+  }
+
+  public function getDatasourceApplicationClass() {
+    return 'PhabricatorProjectApplication';
+  }
+
+  public function getDatasourceFunctions() {
+    return array(
+      'null' => array(
+        'name' => pht('Find results which are not in any projects.'),
+      ),
+    );
+  }
+
+  public function loadResults() {
+    $results = array(
+      $this->buildNullResult(),
+    );
+
+    return $this->filterResultsAgainstTokens($results);
+  }
+
+  protected function evaluateFunction($function, array $argv_list) {
+    $results = array();
+
+    foreach ($argv_list as $argv) {
+      $results[] = new PhabricatorQueryConstraint(
+        PhabricatorQueryConstraint::OPERATOR_NULL,
+        'empty');
+    }
+
+    return $results;
+  }
+
+  public function renderFunctionTokens($function, array $argv_list) {
+    $results = array();
+    foreach ($argv_list as $argv) {
+      $results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
+        $this->buildNullResult());
+    }
+    return $results;
+  }
+
+  private function buildNullResult() {
+    $name = pht('Not In Any Projects');
+
+    return $this->newFunctionResult()
+      ->setUnique(true)
+      ->setPHID('null()')
+      ->setIcon('fa-ban')
+      ->setName('null '.$name)
+      ->setDisplayName($name);
+  }
+
+}
diff --git a/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php b/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php
--- a/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php
+++ b/src/applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php
@@ -30,17 +30,39 @@
     // query to child sources. This makes it easier to implement function
     // sources in terms of real object sources.
     $raw_query = $this->getRawQuery();
+
+    $is_function = false;
     if (self::isFunctionToken($raw_query)) {
-      $function = $this->parseFunction($raw_query, $allow_partial = true);
-      if ($function) {
-        $raw_query = head($function['argv']);
-      }
+      $is_function = true;
     }
 
+    $stack = $this->getFunctionStack();
+
     $results = array();
     foreach ($this->getUsableDatasources() as $source) {
+      $source_stack = $stack;
+
+      $source_query = $raw_query;
+      if ($is_function) {
+        // If this source can't handle the function, skip it.
+        $function = $source->parseFunction($raw_query, $allow_partial = true);
+        if (!$function) {
+          continue;
+        }
+
+        // If this source handles the function directly, strip the function.
+        // Otherwise, this is something like a composite source which has
+        // some internal source which can evaluate the function, but will
+        // perform stripping later.
+        if ($source->shouldStripFunction($function['name'])) {
+          $source_query = head($function['argv']);
+          $source_stack[] = $function['name'];
+        }
+      }
+
       $source
-        ->setRawQuery($raw_query)
+        ->setFunctionStack($source_stack)
+        ->setRawQuery($source_query)
         ->setQuery($this->getQuery())
         ->setViewer($this->getViewer());
 
@@ -106,7 +128,6 @@
     return parent::canEvaluateFunction($function);
   }
 
-
   protected function evaluateFunction($function, array $argv) {
     foreach ($this->getUsableDatasources() as $source) {
       if ($source->canEvaluateFunction($function)) {
diff --git a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php
--- a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php
+++ b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php
@@ -11,6 +11,7 @@
   private $offset;
   private $limit;
   private $parameters = array();
+  private $functionStack = array();
 
   public function setLimit($limit) {
     $this->limit = $limit;
@@ -274,6 +275,14 @@
    * @task functions
    */
   protected function canEvaluateFunction($function) {
+    return $this->shouldStripFunction($function);
+  }
+
+
+  /**
+   * @task functions
+   */
+  protected function shouldStripFunction($function) {
     $functions = $this->getDatasourceFunctions();
     return isset($functions[$function]);
   }
@@ -337,7 +346,7 @@
     $matches = null;
 
     if ($allow_partial) {
-      $ok = preg_match('/^([^(]+)\((.*)$/', $token, $matches);
+      $ok = preg_match('/^([^(]+)\((.*?)\)?$/', $token, $matches);
     } else {
       $ok = preg_match('/^([^(]+)\((.*)\)$/', $token, $matches);
     }
@@ -367,4 +376,28 @@
   }
 
 
+  /**
+   * @task functions
+   */
+  public function setFunctionStack(array $function_stack) {
+    $this->functionStack = $function_stack;
+    return $this;
+  }
+
+
+  /**
+   * @task functions
+   */
+  public function getFunctionStack() {
+    return $this->functionStack;
+  }
+
+
+  /**
+   * @task functions
+   */
+  protected function getCurrentFunction() {
+    return nonempty(last($this->functionStack), null);
+  }
+
 }