diff --git a/mininet/cli.py b/mininet/cli.py
index ea72f8da979858e1c53b5eabc765b4470998e408..a89051dab296cb8aa885a9b3c2149851ba9c5551 100644
--- a/mininet/cli.py
+++ b/mininet/cli.py
@@ -33,7 +33,7 @@
 import time
 
 from mininet.log import info, output, error
-from mininet.term import makeTerms
+from mininet.term import makeTerms, runX11
 from mininet.util import quietRun, isShellBuiltin, dumpNodeConnections
 
 class CLI( Cmd ):
@@ -241,6 +241,17 @@ def do_xterm( self, line, term='xterm' ):
                     node = self.nodemap[ arg ]
                     self.mn.terms += makeTerms( [ node ], term = term )
 
+    def do_x( self, line ):
+        """Create an X11 tunnel to the given node,
+           optionally starting a client."""
+        args = line.split()
+        if not args:
+            error( 'usage: x node [cmd args]...\n' )
+        else:
+            node = self.mn[ args[ 0 ] ]
+            cmd = args[ 1: ]
+            self.mn.terms += runX11( node, cmd )
+
     def do_gterm( self, line ):
         "Spawn gnome-terminal(s) for the given node(s)."
         self.do_xterm( line, term='gterm' )
diff --git a/mininet/term.py b/mininet/term.py
index c99a82484de690bdcd27b32bb15f691b570f0bc0..4c6370cf67c54635c63451c5284361455fb0fb67 100644
--- a/mininet/term.py
+++ b/mininet/term.py
@@ -52,6 +52,12 @@ def makeTerm( node, title='Node', term='xterm', display=None ):
     term = node.popen( cmds[ term ] + [ display, '-e', 'env TERM=ansi bash'] )
     return [ tunnel, term ] if tunnel else [ term ]
 
+def runX11( node, cmd ):
+    "Run an X11 client on a node"
+    display, tunnel = tunnelX11( node )
+    popen = node.popen( cmd )
+    return [ tunnel, popen ]
+
 def cleanUpScreens():
     "Remove moldy socat X11 tunnels."
     errRun( "pkill -9 -f mnexec.*socat" )