diff --git a/.arcconfig b/.arcconfig
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,6 +1,5 @@
 {
-  "project_id" : "arcanist",
-  "conduit_uri" : "https://secure.phabricator.com/",
+  "phabricator.uri" : "https://secure.phabricator.com/",
   "lint.engine" : "PhutilLintEngine",
   "unit.engine" : "PhutilUnitTestEngine",
   "load" : [
diff --git a/scripts/arcanist.php b/scripts/arcanist.php
--- a/scripts/arcanist.php
+++ b/scripts/arcanist.php
@@ -204,8 +204,8 @@
   if ($force_conduit) {
     $conduit_uri = $force_conduit;
   } else {
-    $project_conduit_uri =
-      $configuration_manager->getProjectConfig('conduit_uri');
+    $project_conduit_uri = $configuration_manager->getProjectConfig(
+      'phabricator.uri');
     if ($project_conduit_uri) {
       $conduit_uri = $project_conduit_uri;
     } else {
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
@@ -205,7 +205,7 @@
     'ArcanistBundleTestCase' => 'ArcanistTestCase',
     'ArcanistCSSLintLinter' => 'ArcanistExternalLinter',
     'ArcanistCSSLintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
-    'ArcanistCSharpLinter' => 'ArcanistFutureLinter',
+    'ArcanistCSharpLinter' => 'ArcanistLinter',
     'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow',
     'ArcanistCapabilityNotSupportedException' => 'Exception',
     'ArcanistChooseInvalidRevisionException' => 'Exception',
diff --git a/src/configuration/ArcanistSettings.php b/src/configuration/ArcanistSettings.php
--- a/src/configuration/ArcanistSettings.php
+++ b/src/configuration/ArcanistSettings.php
@@ -32,6 +32,32 @@
           'unit test engines.',
         'example' => '["/var/arc/customlib/src"]',
       ),
+      'repository.callsign' => array(
+        'type' => 'string',
+        'example' => '"X"',
+        'help' => pht(
+          'Associate the working copy with a specific Phabricator repository. '.
+          'Normally, arc can figure this association out on its own, but if '.
+          'your setup is unusual you can use this option to tell it what the '.
+          'desired value is.'),
+      ),
+      'phabricator.uri' => array(
+        'type' => 'string',
+        'legacy' => 'conduit_uri',
+        'example' => '"https://phabricator.mycompany.com/"',
+        'help' => pht(
+          'Associates this working copy with a specific installation of '.
+          'Phabricator.'),
+      ),
+      'project.name' => array(
+        'type' => 'string',
+        'legacy' => 'project_id',
+        'example' => '"arcanist"',
+        'help' => pht(
+          'Associates this working copy with a named Arcanist Project. '.
+          'This is primarily useful if you use SVN and have several different '.
+          'projects in the same repository.'),
+      ),
       'lint.engine' => array(
         'type' => 'string',
         'legacy' => 'lint_engine',
diff --git a/src/repository/api/ArcanistGitAPI.php b/src/repository/api/ArcanistGitAPI.php
--- a/src/repository/api/ArcanistGitAPI.php
+++ b/src/repository/api/ArcanistGitAPI.php
@@ -369,6 +369,18 @@
     if (preg_match('/^\* ([^\(].*)$/m', $stdout, $matches)) {
       return $matches[1];
     }
+
+    return null;
+  }
+
+  public function getRemoteURI() {
+    list($stdout) = $this->execxLocal('remote show -n origin');
+
+    $matches = null;
+    if (preg_match('/^\s*Fetch URL: (.*)$/m', $stdout, $matches)) {
+      return trim($matches[1]);
+    }
+
     return null;
   }
 
diff --git a/src/repository/api/ArcanistMercurialAPI.php b/src/repository/api/ArcanistMercurialAPI.php
--- a/src/repository/api/ArcanistMercurialAPI.php
+++ b/src/repository/api/ArcanistMercurialAPI.php
@@ -1038,4 +1038,16 @@
 
     return array(trim($name), trim($rev));
   }
+
+  public function getRemoteURI() {
+    list($stdout) = $this->execxLocal('paths default');
+
+    $stdout = trim($stdout);
+    if (strlen($stdout)) {
+      return $stdout;
+    }
+
+    return null;
+  }
+
 }
diff --git a/src/repository/api/ArcanistRepositoryAPI.php b/src/repository/api/ArcanistRepositoryAPI.php
--- a/src/repository/api/ArcanistRepositoryAPI.php
+++ b/src/repository/api/ArcanistRepositoryAPI.php
@@ -330,6 +330,8 @@
   abstract public function loadWorkingCopyDifferentialRevisions(
     ConduitClient $conduit,
     array $query);
+  abstract public function getRemoteURI();
+
 
   public function getUnderlyingWorkingCopyRevision() {
     return $this->getWorkingCopyRevision();
@@ -643,4 +645,8 @@
     return $commit;
   }
 
+  public function getRepositoryUUID() {
+    return null;
+  }
+
 }
diff --git a/src/repository/api/ArcanistSubversionAPI.php b/src/repository/api/ArcanistSubversionAPI.php
--- a/src/repository/api/ArcanistSubversionAPI.php
+++ b/src/repository/api/ArcanistSubversionAPI.php
@@ -243,6 +243,10 @@
     return 'svn';
   }
 
+  public function getRemoteURI() {
+    return idx($this->getSVNInfo('/'), 'Repository Root');
+  }
+
   public function buildInfoFuture($path) {
     if ($path == '/') {
       // When the root of a working copy is referenced by a symlink and you
@@ -587,7 +591,7 @@
     return null;
   }
 
-  public function getRepositorySVNUUID() {
+  public function getRepositoryUUID() {
     $info = $this->getSVNInfo('/');
     return $info['Repository UUID'];
   }
diff --git a/src/repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php b/src/repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php
--- a/src/repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php
+++ b/src/repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php
@@ -87,6 +87,7 @@
           'UNSTAGED'    => $f_mod | $f_uns | $f_unc,
           'UNTRACKED'   => $f_unt,
         );
+
         $this->assertEqual($expect_uncommitted, $api->getUncommittedStatus());
 
         $expect_range = array(
diff --git a/src/workflow/ArcanistBaseWorkflow.php b/src/workflow/ArcanistBaseWorkflow.php
--- a/src/workflow/ArcanistBaseWorkflow.php
+++ b/src/workflow/ArcanistBaseWorkflow.php
@@ -31,7 +31,8 @@
  *
  * @task  conduit   Conduit
  * @task  scratch   Scratch Files
- * @group workflow
+ * @task  phabrep   Phabricator Repositories
+ *
  * @stable
  */
 abstract class ArcanistBaseWorkflow extends Phobject {
@@ -64,6 +65,8 @@
   private $stashed;
 
   private $projectInfo;
+  private $repositoryInfo;
+  private $repositoryReasons;
 
   private $arcanistConfiguration;
   private $parentWorkflow;
@@ -1518,4 +1521,187 @@
     return $this->repositoryVersion;
   }
 
+
+/* -(  Phabricator Repositories  )------------------------------------------- */
+
+
+  /**
+   * Get the PHID of the Phabricator repository this working copy corresponds
+   * to. Returns `null` no repository can be identified.
+   *
+   * @return phid|null  Repository PHID, or null if no repository can be
+   *                    identified.
+   *
+   * @task phabrep
+   */
+  protected function getRepositoryPHID() {
+    return idx($this->getRepositoryInformation(), 'phid');
+  }
+
+
+  /**
+   * Get the callsign of the Phabricator repository this working copy
+   * corresponds to. Returns `null` no repository can be identified.
+   *
+   * @return string|null  Repository callsign, or null if no repository can be
+   *                      identified.
+   *
+   * @task phabrep
+   */
+  protected function getRepositoryCallsign() {
+    return idx($this->getRepositoryInformation(), 'callsign');
+  }
+
+
+  /**
+   * Get human-readable reasoning explaining how `arc` evaluated which
+   * Phabricator repository corresponds to this working copy. Used by
+   * `arc which` to explain the process to users.
+   *
+   * @return list<string> Human-readable explanation of the repository
+   *                      association process.
+   *
+   * @task phabrep
+   */
+  protected function getRepositoryReasons() {
+    $this->getRepositoryInformation();
+    return $this->repositoryReasons;
+  }
+
+
+  /**
+   * @task phabrep
+   */
+  private function getRepositoryInformation() {
+    if ($this->repositoryInfo === null) {
+      list($info, $reasons) = $this->loadRepositoryInformation();
+      $this->repositoryInfo = $info;
+      $this->repositoryReasons = $reasons;
+    }
+
+    return $this->repositoryInfo;
+  }
+
+
+  /**
+   * @task phabrep
+   */
+  private function loadRepositoryInformation() {
+    list($query, $reasons) = $this->getRepositoryQuery();
+    if (!$query) {
+      return array(null, $reasons);
+    }
+
+    try {
+      $results = $this->getConduit()->callMethodSynchronous(
+        'repository.query',
+        $query);
+    } catch (ConduitClientException $ex) {
+      if ($ex->getErrorCode() == 'ERR-CONDUIT-CALL') {
+        $reasons[] = pht(
+          'This version of Arcanist is more recent than the version of '.
+          'Phabricator you are connecting to: the Phabricator install is '.
+          'out of date and does not have support for identifying '.
+          'repositories by callsign or URI. Update Phabricator to enable '.
+          'these features.');
+        return array(null, $reasons);
+      }
+      throw $ex;
+    }
+
+    $result = null;
+    if (!$results) {
+      $reasons[] = pht(
+        'No repositories matched the query. Check that your configuration '.
+        'is correct, or use "repository.callsign" to select a repository '.
+        'explicitly.');
+    } else if (count($results) > 1) {
+      $reasons[] = pht(
+        'Multiple repostories (%s) matched the query. You can use the '.
+        '"repository.callsign" configuration to select the one you want.',
+        implode(', ', ipull($results, 'callsign')));
+    } else {
+      $result = head($results);
+      $reasons[] = pht('Found a unique matching repository.');
+    }
+
+    return array($result, $reasons);
+  }
+
+
+  /**
+   * @task phabrep
+   */
+  private function getRepositoryQuery() {
+    $reasons = array();
+
+    $callsign = $this->getConfigFromAnySource('repository.callsign');
+    if ($callsign) {
+      $query = array(
+        'callsigns' => array($callsign),
+      );
+      $reasons[] = pht(
+        'Configuration value "repository.callsign" is set to "%s".',
+        $callsign);
+      return array($query, $reasons);
+    } else {
+      $reasons[] = pht(
+        'Configuration value "repository.callsign" is empty.');
+    }
+
+    $project_info = $this->getProjectInfo();
+    if ($this->getProjectInfo()) {
+      if (!empty($project_info['repository']['callsign'])) {
+        $callsign = $project_info['repository']['callsign'];
+        $query = array(
+          'callsigns' => array($callsign),
+        );
+        $reasons[] = pht(
+          'Configuration value "project.id" is set to "%s"; this project '.
+          'is associated with the "%s" repository.',
+          $this->getWorkingCopy()->getProjectID(),
+          $callsign);
+        return array($query, $reasons);
+      } else {
+        $reasons[] = pht(
+          'Configuration value "project.id" is set to "%s", but this '.
+          'project is not associated with a repository.');
+      }
+    } else {
+      $reasons[] = pht(
+        'Configuration value "project.id" is empty.');
+    }
+
+    $uuid = $this->getRepositoryAPI()->getRepositoryUUID();
+    if ($uuid !== null) {
+      $query = array(
+        'uuids' => array($uuid),
+      );
+      $reasons[] = pht(
+        'The UUID for this working copy is "%s".',
+        $uuid);
+      return array($query, $reasons);
+    } else {
+      $reasons[] = pht(
+        'This repository has no VCS UUID (this is normal for git/hg).');
+    }
+
+    $remote_uri = $this->getRepositoryAPI()->getRemoteURI();
+    if ($remote_uri !== null) {
+      $query = array(
+        'remoteURIs' => array($remote_uri),
+      );
+      $reasons[] = pht(
+        'The remote URI for this working copy is "%s".',
+        $remote_uri);
+      return array($query, $reasons);
+    } else {
+      $reasons[] = pht(
+        'Unable to determine the remote URI for this repository.');
+    }
+
+    return array(null, $reasons);
+  }
+
+
 }
diff --git a/src/workflow/ArcanistDiffWorkflow.php b/src/workflow/ArcanistDiffWorkflow.php
--- a/src/workflow/ArcanistDiffWorkflow.php
+++ b/src/workflow/ArcanistDiffWorkflow.php
@@ -508,9 +508,9 @@
     }
 
     $diff_spec = array(
-      'changes'                   => mpull($changes, 'toDictionary'),
-      'lintStatus'                => $this->getLintStatus($lint_result),
-      'unitStatus'                => $this->getUnitStatus($unit_result),
+      'changes' => mpull($changes, 'toDictionary'),
+      'lintStatus' => $this->getLintStatus($lint_result),
+      'unitStatus' => $this->getUnitStatus($unit_result),
     ) + $this->buildDiffSpecification();
 
     $conduit = $this->getConduit();
@@ -2243,6 +2243,7 @@
       $vcs            = $repository_api->getSourceControlSystemName();
       $source_path    = $repository_api->getPath();
       $branch         = $repository_api->getBranchName();
+      $repo_uuid      = $repository_api->getRepositoryUUID();
 
       if ($repository_api instanceof ArcanistGitAPI) {
         $info = $this->getGitParentLogInfo();
@@ -2258,8 +2259,6 @@
         if ($info['uuid']) {
           $repo_uuid = $info['uuid'];
         }
-      } else if ($repository_api instanceof ArcanistSubversionAPI) {
-        $repo_uuid = $repository_api->getRepositorySVNUUID();
       } else if ($repository_api instanceof ArcanistMercurialAPI) {
 
         $bookmark = $repository_api->getActiveBookmark();
@@ -2280,7 +2279,7 @@
       $project_id = $this->getWorkingCopy()->getProjectID();
     }
 
-    return array(
+    $data = array(
       'sourceMachine'             => php_uname('n'),
       'sourcePath'                => $source_path,
       'branch'                    => $branch,
@@ -2288,12 +2287,16 @@
       'sourceControlSystem'       => $vcs,
       'sourceControlPath'         => $base_path,
       'sourceControlBaseRevision' => $base_revision,
-      'parentRevisionID'          => $parent,
-      'repositoryUUID'            => $repo_uuid,
       'creationMethod'            => 'arc',
       'arcanistProject'           => $project_id,
-      'authorPHID'                => $this->getUserPHID(),
     );
+
+    $repository_phid = $this->getRepositoryPHID();
+    if ($repository_phid) {
+      $data['repositoryPHID'] = $repository_phid;
+    }
+
+    return $data;
   }
 
 
diff --git a/src/workflow/ArcanistWhichWorkflow.php b/src/workflow/ArcanistWhichWorkflow.php
--- a/src/workflow/ArcanistWhichWorkflow.php
+++ b/src/workflow/ArcanistWhichWorkflow.php
@@ -22,7 +22,8 @@
   public function getCommandHelp() {
     return phutil_console_format(<<<EOTEXT
           Supports: svn, git, hg
-          Shows which commits 'arc diff' will select, and which revision is in
+          Shows which repository the current working copy corresponds to,
+          which commits 'arc diff' will select, and which revision is in
           the working copy (or which revisions, if more than one matches).
 EOTEXT
       );
@@ -69,6 +70,11 @@
 
   public function run() {
 
+    $console = PhutilConsole::getConsole();
+
+    $this->printRepositorySection();
+    $console->writeOut("\n");
+
     $repository_api = $this->getRepositoryAPI();
 
     $arg_commit = $this->getArgument('commit');
@@ -184,4 +190,34 @@
 
     return 0;
   }
+
+  private function printRepositorySection() {
+    $console = PhutilConsole::getConsole();
+    $console->writeOut("**%s**\n", pht('REPOSITORY'));
+
+    $callsign = $this->getRepositoryCallsign();
+
+    $console->writeOut(
+      "%s\n\n",
+      pht(
+        'To identify the repository associated with this working copy, '.
+        'arc followed this process:'));
+
+    foreach ($this->getRepositoryReasons() as $reason) {
+      $reason = phutil_console_wrap($reason, 4);
+      $console->writeOut("%s\n\n", $reason);
+    }
+
+    if ($callsign) {
+      $console->writeOut(
+        "%s\n",
+        pht('This working copy is associated with the %s repository.',
+        phutil_console_format('**%s**', $callsign)));
+    } else {
+      $console->writeOut(
+        "%s\n",
+        pht('This working copy is not associated with any repository.'));
+    }
+  }
+
 }
diff --git a/src/workingcopyidentity/ArcanistWorkingCopyIdentity.php b/src/workingcopyidentity/ArcanistWorkingCopyIdentity.php
--- a/src/workingcopyidentity/ArcanistWorkingCopyIdentity.php
+++ b/src/workingcopyidentity/ArcanistWorkingCopyIdentity.php
@@ -187,6 +187,7 @@
 
   private static function parseRawConfigFile($raw_config, $from_where) {
     $proj = json_decode($raw_config, true);
+
     if (!is_array($proj)) {
       throw new Exception(
         "Unable to parse '.arcconfig' file '{$from_where}'. The file contents ".
@@ -194,16 +195,7 @@
         "FILE CONTENTS\n".
         substr($raw_config, 0, 2048));
     }
-    $required_keys = array(
-      'project_id',
-    );
-    foreach ($required_keys as $key) {
-      if (!array_key_exists($key, $proj)) {
-        throw new Exception(
-          "Required key '{$key}' is missing from '.arcconfig' file ".
-          "'{$from_where}'.");
-      }
-    }
+
     return $proj;
   }
 
@@ -213,6 +205,12 @@
   }
 
   public function getProjectID() {
+    $project_id = $this->getProjectConfig('project.name');
+    if ($project_id) {
+      return $project_id;
+    }
+
+    // This is an older name for the setting.
     return $this->getProjectConfig('project_id');
   }