diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
index 975ec4ce961cc23c27773e6c357348f1e8e2b101_bWVyY3VyaWFsL2Rpc3BhdGNoLnB5..208fc9ad6a48887f30aecbc1b0df0f55b777ce1b_bWVyY3VyaWFsL2Rpc3BhdGNoLnB5 100644
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -218,6 +218,7 @@
             return
 
         if self.definition.startswith('!'):
+            self.shell = True
             def fn(ui, *args):
                 env = {'HG_ARGS': ' '.join((self.name,) + args)}
                 def _checkvar(m):
@@ -404,18 +405,11 @@
               result=ret, pats=cmdpats, opts=cmdoptions)
     return ret
 
-_loaded = set()
-def _dispatch(ui, args):
-    # read --config before doing anything else
-    # (e.g. to change trust settings for reading .hg/hgrc)
-    _parseconfig(ui, _earlygetopt(['--config'], args))
-
-    # check for cwd
-    cwd = _earlygetopt(['--cwd'], args)
-    if cwd:
-        os.chdir(cwd[-1])
-
-    # read the local repository .hgrc into a local ui object
+def _getlocal(ui, rpath):
+    """Return (path, local ui object) for the given target path.
+    
+    Takes paths in [cwd]/.hg/hgrc into account."
+    """
     try:
         wd = os.getcwd()
     except OSError, e:
@@ -431,10 +425,8 @@
         except IOError:
             pass
 
-    # now we can expand paths, even ones in .hg/hgrc
-    rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
     if rpath:
         path = lui.expandpath(rpath[-1])
         lui = ui.copy()
         lui.readconfig(os.path.join(path, ".hg", "hgrc"))
 
@@ -436,8 +428,61 @@
     if rpath:
         path = lui.expandpath(rpath[-1])
         lui = ui.copy()
         lui.readconfig(os.path.join(path, ".hg", "hgrc"))
 
+    return path, lui
+
+def _checkshellalias(ui, args):
+    cwd = os.getcwd()
+    options = {}
+    args = fancyopts.fancyopts(args, commands.globalopts, options)
+
+    if not args:
+        return
+
+    _parseconfig(ui, options['config'])
+    if options['cwd']:
+        os.chdir(options['cwd'])
+
+    path, lui = _getlocal(ui, [options['repository']])
+
+    cmdtable = commands.table.copy()
+    addaliases(lui, cmdtable)
+
+    cmd = args[0]
+    try:
+        aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
+    except error.UnknownCommand:
+        os.chdir(cwd)
+        return
+
+    cmd = aliases[0]
+    fn = entry[0]
+
+    if cmd and hasattr(fn, 'shell'):
+        d = lambda: fn(ui, *args[1:])
+        return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
+
+    os.chdir(cwd)
+
+_loaded = set()
+def _dispatch(ui, args):
+    shellaliasfn = _checkshellalias(ui, args)
+    if shellaliasfn:
+        return shellaliasfn()
+
+    # read --config before doing anything else
+    # (e.g. to change trust settings for reading .hg/hgrc)
+    _parseconfig(ui, _earlygetopt(['--config'], args))
+
+    # check for cwd
+    cwd = _earlygetopt(['--cwd'], args)
+    if cwd:
+        os.chdir(cwd[-1])
+
+    rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
+    path, lui = _getlocal(ui, rpath)
+
     # Configure extensions in phases: uisetup, extsetup, cmdtable, and
     # reposetup. Programs like TortoiseHg will call _dispatch several
     # times so we keep track of configured extensions in _loaded.
diff --git a/tests/test-alias.t b/tests/test-alias.t
index 975ec4ce961cc23c27773e6c357348f1e8e2b101_dGVzdHMvdGVzdC1hbGlhcy50..208fc9ad6a48887f30aecbc1b0df0f55b777ce1b_dGVzdHMvdGVzdC1hbGlhcy50 100644
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -23,6 +23,7 @@
   > echo2 = !echo '\$2'
   > echo13 = !echo '\$1' '\$3'
   > count = !hg log -r '\$@' --template='.' | wc -c | sed -e 's/ //g'
+  > mcount = !hg log \$@ --template='.' | wc -c | sed -e 's/ //g'
   > rt = root
   > 
   > [defaults]
@@ -158,5 +159,7 @@
   
   $ hg blank foo
   
+  $ hg self
+  self
   $ hg echo
   
@@ -161,7 +164,5 @@
   $ hg echo
   
-  $ hg self
-  self
   $ hg echo foo
   foo
   $ hg echo 'test $2' foo
@@ -180,6 +181,59 @@
   1
   $ hg count 'branch(default)'
   2
+  $ hg mcount -r '"branch(default)"'
+  2
+
+
+shell aliases with global options
+
+  $ hg init sub
+  $ cd sub
+  $ hg count 'branch(default)'
+  0
+  $ hg -v count 'branch(default)'
+  0
+  $ hg -R .. count 'branch(default)'
+  0
+  $ hg --cwd .. count 'branch(default)'
+  2
+  $ hg echo --cwd ..
+  --cwd ..
+
+
+repo specific shell aliases
+
+  $ cat >> .hg/hgrc <<EOF
+  > [alias]
+  > subalias = !echo sub \$@
+  > EOF
+  $ cat >> ../.hg/hgrc <<EOF
+  > [alias]
+  > mainalias = !echo main \$@
+  > EOF
+
+
+shell alias defined in current repo
+
+  $ hg subalias
+  sub
+  $ hg --cwd .. subalias > /dev/null
+  hg: unknown command 'subalias'
+  [255]
+  $ hg -R .. subalias > /dev/null
+  hg: unknown command 'subalias'
+  [255]
+
+
+shell alias defined in other repo
+
+  $ hg mainalias > /dev/null
+  hg: unknown command 'mainalias'
+  [255]
+  $ hg -R .. mainalias
+  main
+  $ hg --cwd .. mainalias
+  main
 
 
 invalid arguments