diff --git a/completion.bash b/completion.bash
index 0b52d29c..09291d5c 100644
--- a/completion.bash
+++ b/completion.bash
@@ -14,6 +14,9 @@
 
 # Programmable bash completion.  https://github.com/scop/bash-completion
 
+# TODO: Handle interspersed options.  We handle `repo h<tab>`, but not
+# `repo --time h<tab>`.
+
 # Complete the list of repo subcommands.
 __complete_repo_list_commands() {
   local repo=${COMP_WORDS[0]}
@@ -37,6 +40,7 @@ __complete_repo_list_branches() {
 __complete_repo_list_projects() {
   local repo=${COMP_WORDS[0]}
   "${repo}" list -n 2>/dev/null
+  "${repo}" list -p --relative-to=. 2>/dev/null
 }
 
 # Complete the repo <command> argument.
@@ -66,6 +70,48 @@ __complete_repo_command_projects() {
   COMPREPLY=($(compgen -W "$(__complete_repo_list_projects)" -- "${current}"))
 }
 
+# Complete `repo help`.
+__complete_repo_command_help() {
+  local current=$1
+  # CWORD=1 is "start".
+  # CWORD=2 is the <subcommand> which we complete here.
+  if [[ ${COMP_CWORD} -eq 2 ]]; then
+    COMPREPLY=(
+      $(compgen -W "$(__complete_repo_list_commands)" -- "${current}")
+    )
+  fi
+}
+
+# Complete `repo forall`.
+__complete_repo_command_forall() {
+  local current=$1
+  # CWORD=1 is "forall".
+  # CWORD=2+ are <projects> *until* we hit the -c option.
+  local i
+  for (( i = 0; i < COMP_CWORD; ++i )); do
+    if [[ "${COMP_WORDS[i]}" == "-c" ]]; then
+      return 0
+    fi
+  done
+
+  COMPREPLY=(
+    $(compgen -W "$(__complete_repo_list_projects)" -- "${current}")
+  )
+}
+
+# Complete `repo start`.
+__complete_repo_command_start() {
+  local current=$1
+  # CWORD=1 is "start".
+  # CWORD=2 is the <branch> which we don't complete.
+  # CWORD=3+ are <projects> which we complete here.
+  if [[ ${COMP_CWORD} -gt 2 ]]; then
+    COMPREPLY=(
+      $(compgen -W "$(__complete_repo_list_projects)" -- "${current}")
+    )
+  fi
+}
+
 # Complete the repo subcommand arguments.
 __complete_repo_arg() {
   if [[ ${COMP_CWORD} -le 1 ]]; then
@@ -86,21 +132,8 @@ __complete_repo_arg() {
     return 0
     ;;
 
-  help)
-    if [[ ${COMP_CWORD} -eq 2 ]]; then
-      COMPREPLY=(
-        $(compgen -W "$(__complete_repo_list_commands)" -- "${current}")
-      )
-    fi
-    return 0
-    ;;
-
-  start)
-    if [[ ${COMP_CWORD} -gt 2 ]]; then
-      COMPREPLY=(
-        $(compgen -W "$(__complete_repo_list_projects)" -- "${current}")
-      )
-    fi
+  help|start|forall)
+    __complete_repo_command_${command} "${current}"
     return 0
     ;;
 
@@ -118,4 +151,6 @@ __complete_repo() {
   return 0
 }
 
-complete -F __complete_repo repo
+# Fallback to the default complete methods if we aren't able to provide anything
+# useful.  This will allow e.g. local paths to be used when it makes sense.
+complete -F __complete_repo -o bashdefault -o default repo
diff --git a/git_config.py b/git_config.py
index 4416bfa9..01183a0a 100644
--- a/git_config.py
+++ b/git_config.py
@@ -31,7 +31,8 @@ from repo_trace import Trace
 from git_command import GitCommand
 from git_refs import R_CHANGES, R_HEADS, R_TAGS
 
-# Prefix Add all the data of SyncAnalysisState object.
+# Prefix that is prepended to all the keys of SyncAnalysisState's data
+# that is saved in the config.
 SYNC_STATE_PREFIX = 'syncstate.'
 
 ID_RE = re.compile(r'^[0-9a-f]{40}$')
@@ -271,10 +272,7 @@ class GitConfig(object):
     return {k: v for k, v in self.DumpConfigDict().items() if k.startswith(SYNC_STATE_PREFIX)}
 
   def UpdateSyncAnalysisState(self, options, superproject_logging_data):
-    """Update Config's SyncAnalysisState with the latest sync data.
-
-    Creates SyncAnalysisState object with |options| and |superproject_logging_data|
-    which in turn persists the data into the |self| object.
+    """Update Config's SYNC_STATE_PREFIX* data with the latest sync data.
 
     Args:
       options: Options passed to sync returned from optparse. See _Options().
@@ -743,7 +741,7 @@ class Branch(object):
 
 
 class SyncAnalysisState():
-  """Configuration options related to logging of Sync state for analysis.
+  """Configuration options related to logging of sync state for analysis.
 
   This object is versioned.
   """
@@ -786,7 +784,7 @@ class SyncAnalysisState():
   def _Set(self, key, value):
     """Set the |value| for a |key| in the |_config| member.
 
-    Every key is stored by prepending the value of SYNC_STATE_PREFIX constant to it.
+    |key| is prepended with the value of SYNC_STATE_PREFIX constant.
 
     Args:
       key: Name of the key.
diff --git a/git_superproject.py b/git_superproject.py
index 86100960..8769355c 100644
--- a/git_superproject.py
+++ b/git_superproject.py
@@ -106,6 +106,11 @@ class Superproject(object):
     """Returns a dictionary of projects and their commit ids."""
     return self._project_commit_ids
 
+  @property
+  def manifest_path(self):
+    """Returns the manifest path if the path exists or None."""
+    return self._manifest_path if os.path.exists(self._manifest_path) else None
+
   def _GetBranch(self):
     """Returns the branch name for getting the approved manifest."""
     p = self._manifest.manifestProject
diff --git a/main.py b/main.py
index f6631f5f..2050cabb 100755
--- a/main.py
+++ b/main.py
@@ -95,6 +95,8 @@ global_options = optparse.OptionParser(
     add_help_option=False)
 global_options.add_option('-h', '--help', action='store_true',
                           help='show this help message and exit')
+global_options.add_option('--help-all', action='store_true',
+                          help='show this help message with all subcommands and exit')
 global_options.add_option('-p', '--paginate',
                           dest='pager', action='store_true',
                           help='display command output in the pager')
@@ -116,6 +118,10 @@ global_options.add_option('--time',
 global_options.add_option('--version',
                           dest='show_version', action='store_true',
                           help='display this version of repo')
+global_options.add_option('--show-toplevel',
+                          action='store_true',
+                          help='display the path of the top-level directory of '
+                               'the repo client checkout')
 global_options.add_option('--event-log',
                           dest='event_log', action='store',
                           help='filename of event log to append timeline to')
@@ -128,34 +134,40 @@ class _Repo(object):
     self.repodir = repodir
     self.commands = all_commands
 
+  def _PrintHelp(self, short: bool = False, all_commands: bool = False):
+    """Show --help screen."""
+    global_options.print_help()
+    print()
+    if short:
+      commands = ' '.join(sorted(self.commands))
+      wrapped_commands = textwrap.wrap(commands, width=77)
+      print('Available commands:\n  %s' % ('\n  '.join(wrapped_commands),))
+      print('\nRun `repo help <command>` for command-specific details.')
+      print('Bug reports:', Wrapper().BUG_URL)
+    else:
+      cmd = self.commands['help']()
+      if all_commands:
+        cmd.PrintAllCommandsBody()
+      else:
+        cmd.PrintCommonCommandsBody()
+
   def _ParseArgs(self, argv):
     """Parse the main `repo` command line options."""
-    name = None
-    glob = []
-
-    for i in range(len(argv)):
-      if not argv[i].startswith('-'):
-        name = argv[i]
-        if i > 0:
-          glob = argv[:i]
+    for i, arg in enumerate(argv):
+      if not arg.startswith('-'):
+        name = arg
+        glob = argv[:i]
         argv = argv[i + 1:]
         break
-    if not name:
+    else:
+      name = None
       glob = argv
-      name = 'help'
       argv = []
     gopts, _gargs = global_options.parse_args(glob)
 
-    name, alias_args = self._ExpandAlias(name)
-    argv = alias_args + argv
-
-    if gopts.help:
-      global_options.print_help()
-      commands = ' '.join(sorted(self.commands))
-      wrapped_commands = textwrap.wrap(commands, width=77)
-      print('\nAvailable commands:\n  %s' % ('\n  '.join(wrapped_commands),))
-      print('\nRun `repo help <command>` for command-specific details.')
-      global_options.exit()
+    if name:
+      name, alias_args = self._ExpandAlias(name)
+      argv = alias_args + argv
 
     return (name, gopts, argv)
 
@@ -186,12 +198,21 @@ class _Repo(object):
 
     if gopts.trace:
       SetTrace()
-    if gopts.show_version:
-      if name == 'help':
-        name = 'version'
-      else:
-        print('fatal: invalid usage of --version', file=sys.stderr)
-        return 1
+
+    # Handle options that terminate quickly first.
+    if gopts.help or gopts.help_all:
+      self._PrintHelp(short=False, all_commands=gopts.help_all)
+      return 0
+    elif gopts.show_version:
+      # Always allow global --version regardless of subcommand validity.
+      name = 'version'
+    elif gopts.show_toplevel:
+      print(os.path.dirname(self.repodir))
+      return 0
+    elif not name:
+      # No subcommand specified, so show the help/subcommand.
+      self._PrintHelp(short=True)
+      return 1
 
     SetDefaultColoring(gopts.color)
 
diff --git a/man/repo-list.1 b/man/repo-list.1
index a86315ae..7f85e612 100644
--- a/man/repo-list.1
+++ b/man/repo-list.1
@@ -27,15 +27,19 @@ project is in
 \fB\-a\fR, \fB\-\-all\fR
 show projects regardless of checkout state
 .TP
-\fB\-f\fR, \fB\-\-fullpath\fR
-display the full work tree path instead of the
-relative path
-.TP
 \fB\-n\fR, \fB\-\-name\-only\fR
 display only the name of the repository
 .TP
 \fB\-p\fR, \fB\-\-path\-only\fR
 display only the path of the repository
+.TP
+\fB\-f\fR, \fB\-\-fullpath\fR
+display the full work tree path instead of the
+relative path
+.TP
+\fB\-\-relative\-to\fR=\fI\,PATH\/\fR
+display paths relative to this one (default: top of
+repo client checkout)
 .SS Logging options:
 .TP
 \fB\-v\fR, \fB\-\-verbose\fR
diff --git a/man/repo-manifest.1 b/man/repo-manifest.1
index e42cc42e..be467607 100644
--- a/man/repo-manifest.1
+++ b/man/repo-manifest.1
@@ -36,6 +36,9 @@ output manifest in JSON format (experimental)
 \fB\-\-pretty\fR
 format output for humans to read
 .TP
+\fB\-\-no\-local\-manifests\fR
+ignore local manifests
+.TP
 \fB\-o\fR \-|NAME.xml, \fB\-\-output\-file\fR=\fI\,\-\/\fR|NAME.xml
 file to save the manifest to
 .SS Logging options:
@@ -95,7 +98,7 @@ include*)>
 .IP
 <!ELEMENT notice (#PCDATA)>
 .IP
-<!ELEMENT remote EMPTY>
+<!ELEMENT remote (annotation*)>
 <!ATTLIST remote name         ID    #REQUIRED>
 <!ATTLIST remote alias        CDATA #IMPLIED>
 <!ATTLIST remote fetch        CDATA #REQUIRED>
@@ -393,13 +396,13 @@ Same syntax as the corresponding element of `project`.
 .PP
 Element annotation
 .PP
-Zero or more annotation elements may be specified as children of a project
-element. Each element describes a name\-value pair that will be exported into
-each project's environment during a 'forall' command, prefixed with REPO__. In
-addition, there is an optional attribute "keep" which accepts the case
-insensitive values "true" (default) or "false". This attribute determines
-whether or not the annotation will be kept when exported with the manifest
-subcommand.
+Zero or more annotation elements may be specified as children of a project or
+remote element. Each element describes a name\-value pair. For projects, this
+name\-value pair will be exported into each project's environment during a
+\&'forall' command, prefixed with `REPO__`. In addition, there is an optional
+attribute "keep" which accepts the case insensitive values "true" (default) or
+"false". This attribute determines whether or not the annotation will be kept
+when exported with the manifest subcommand.
 .PP
 Element copyfile
 .PP
diff --git a/man/repo.1 b/man/repo.1
index 0bc3acdb..4aa76380 100644
--- a/man/repo.1
+++ b/man/repo.1
@@ -2,9 +2,48 @@
 .TH REPO "1" "July 2021" "repo" "Repo Manual"
 .SH NAME
 repo \- repository management tool built on top of git
-.SH DESCRIPTION
-usage: repo COMMAND [ARGS]
-The complete list of recognized repo commands are:
+.SH SYNOPSIS
+.B repo
+[\fI\,-p|--paginate|--no-pager\/\fR] \fI\,COMMAND \/\fR[\fI\,ARGS\/\fR]
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+show this help message and exit
+.TP
+\fB\-\-help\-all\fR
+show this help message with all subcommands and exit
+.TP
+\fB\-p\fR, \fB\-\-paginate\fR
+display command output in the pager
+.TP
+\fB\-\-no\-pager\fR
+disable the pager
+.TP
+\fB\-\-color\fR=\fI\,COLOR\/\fR
+control color usage: auto, always, never
+.TP
+\fB\-\-trace\fR
+trace git command execution (REPO_TRACE=1)
+.TP
+\fB\-\-trace\-python\fR
+trace python command execution
+.TP
+\fB\-\-time\fR
+time repo command execution
+.TP
+\fB\-\-version\fR
+display this version of repo
+.TP
+\fB\-\-show\-toplevel\fR
+display the path of the top\-level directory of the
+repo client checkout
+.TP
+\fB\-\-event\-log\fR=\fI\,EVENT_LOG\/\fR
+filename of event log to append timeline to
+.TP
+\fB\-\-git\-trace2\-event\-log\fR=\fI\,GIT_TRACE2_EVENT_LOG\/\fR
+directory to write git trace2 event log to
+.SS "The complete list of recognized repo commands are:"
 .TP
 abandon
 Permanently abandon a development branch
@@ -91,3 +130,4 @@ version
 Display the version of repo
 .PP
 See 'repo help <command>' for more information on a specific command.
+Bug reports: https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue
diff --git a/release/update-manpages b/release/update-manpages
index 3aeee206..f841f306 100755
--- a/release/update-manpages
+++ b/release/update-manpages
@@ -59,7 +59,7 @@ def main(argv):
   cmdlist.append(['help2man', '-N', '-n', 'repository management tool built on top of git',
     '-S', 'repo', '-m', 'Repo Manual', f'--version-string={version}',
     '-o', MANDIR.joinpath('repo.1'), TOPDIR.joinpath('repo'),
-    '-h', 'help --all'])
+    '-h', '--help-all'])
 
   with tempfile.TemporaryDirectory() as tempdir:
     repo_dir = Path(tempdir) / '.repo'
diff --git a/subcmds/help.py b/subcmds/help.py
index f302e75c..1a60ef45 100644
--- a/subcmds/help.py
+++ b/subcmds/help.py
@@ -50,14 +50,21 @@ Displays detailed usage information about a command.
 
   def _PrintAllCommands(self):
     print('usage: repo COMMAND [ARGS]')
+    self.PrintAllCommandsBody()
+
+  def PrintAllCommandsBody(self):
     print('The complete list of recognized repo commands are:')
     commandNames = list(sorted(all_commands))
     self._PrintCommands(commandNames)
     print("See 'repo help <command>' for more information on a "
           'specific command.')
+    print('Bug reports:', Wrapper().BUG_URL)
 
   def _PrintCommonCommands(self):
     print('usage: repo COMMAND [ARGS]')
+    self.PrintCommonCommandsBody()
+
+  def PrintCommonCommandsBody(self):
     print('The most commonly used repo commands are:')
 
     def gitc_supported(cmd):
diff --git a/subcmds/list.py b/subcmds/list.py
index 8d0c5640..6adf85b7 100644
--- a/subcmds/list.py
+++ b/subcmds/list.py
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import os
+
 from command import Command, MirrorSafeCommand
 
 
@@ -43,20 +45,26 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'.
     p.add_option('-a', '--all',
                  action='store_true',
                  help='show projects regardless of checkout state')
-    p.add_option('-f', '--fullpath',
-                 dest='fullpath', action='store_true',
-                 help='display the full work tree path instead of the relative path')
     p.add_option('-n', '--name-only',
                  dest='name_only', action='store_true',
                  help='display only the name of the repository')
     p.add_option('-p', '--path-only',
                  dest='path_only', action='store_true',
                  help='display only the path of the repository')
+    p.add_option('-f', '--fullpath',
+                 dest='fullpath', action='store_true',
+                 help='display the full work tree path instead of the relative path')
+    p.add_option('--relative-to', metavar='PATH',
+                 help='display paths relative to this one (default: top of repo client checkout)')
 
   def ValidateOptions(self, opt, args):
     if opt.fullpath and opt.name_only:
       self.OptionParser.error('cannot combine -f and -n')
 
+    # Resolve any symlinks so the output is stable.
+    if opt.relative_to:
+      opt.relative_to = os.path.realpath(opt.relative_to)
+
   def Execute(self, opt, args):
     """List all projects and the associated directories.
 
@@ -76,6 +84,8 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'.
     def _getpath(x):
       if opt.fullpath:
         return x.worktree
+      if opt.relative_to:
+        return os.path.relpath(x.worktree, opt.relative_to)
       return x.relpath
 
     lines = []
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 11f71bf1..36b15bf0 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -302,6 +302,12 @@ later is required to fix a server side protocol bug.
                                                  self.repodir,
                                                  self.git_event_log,
                                                  quiet=opt.quiet)
+    if opt.local_only:
+      manifest_path = superproject.manifest_path
+      if manifest_path:
+        self._ReloadManifest(manifest_path, load_local_manifests)
+      return manifest_path
+
     all_projects = self.GetProjects(args,
                                     missing_ok=True,
                                     submodules_ok=opt.fetch_submodules)
@@ -1080,11 +1086,11 @@ later is required to fix a server side protocol bug.
             file=sys.stderr)
       sys.exit(1)
 
-    # Log the previous sync state from the config.
+    # Log the previous sync analysis state from the config.
     self.git_event_log.LogConfigEvents(mp.config.GetSyncAnalysisStateData(),
                                        'previous_sync_state')
 
-    # Update and log with the new sync state.
+    # Update and log with the new sync analysis state.
     mp.config.UpdateSyncAnalysisState(opt, superproject_logging_data)
     self.git_event_log.LogConfigEvents(mp.config.GetSyncAnalysisStateData(),
                                        'current_sync_state')
diff --git a/tests/fixtures/test.gitconfig b/tests/fixtures/test.gitconfig
index 002a4a33..958fb205 100644
--- a/tests/fixtures/test.gitconfig
+++ b/tests/fixtures/test.gitconfig
@@ -12,7 +12,7 @@
 	intm = 10m
 	intg = 10g
 [syncstate "main"]
-	synctime = 2021-07-28T19:42:03.866355Z
+	synctime = 2021-07-28T21:16:10.873226Z
 	version = 1
 [syncstate "sys"]
 	argv = ['/usr/bin/pytest-3']