diff --git a/.gitignore b/.gitignore
index 74effdcf58a01480592bf15e81c9f5c8324df086..f51b7cb9fff5a1148a8c3e6cab1281f6770013d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ msg_gen/
 src/dynamic_graph_bridge/
 bin/
 build/
+srv_gen/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1ecec3be53c2750b037c1939a00104a08283de49..2f4dd4181b00c9da193d9b8fe8e5d8863dfe31da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,11 +11,13 @@ set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
 set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
 
 rosbuild_genmsg()
+rosbuild_gensrv()
 
 rosbuild_add_boost_directories()
 
 pkg_check_modules(JRL_MAL REQUIRED jrl-mal)
 pkg_check_modules(DYNAMIC_GRAPH REQUIRED dynamic-graph)
+pkg_check_modules(DYNAMIC_GRAPH_PYTHON REQUIRED dynamic-graph-python)
 pkg_check_modules(SOT_CORE REQUIRED sot-core)
 
 include_directories(include)
@@ -60,12 +62,28 @@ target_link_libraries(ros_joint_state ros_bridge)
 target_link_libraries(ros_joint_state
   ${JRL_MAL_LIBRARIES} ${DYNAMIC_GRAPH_LIBRARIES} ${SOT_CORE_LIBRARIES})
 
+rosbuild_add_library(ros_interpreter
+  src/ros_interpreter.cpp)
+rosbuild_add_compile_flags(ros_interpreter
+  ${JRL_MAL_CFLAGS} ${DYNAMIC_GRAPH_CFLAGS} ${DYNAMIC_GRAPH_PYTHON_CFLAGS}
+  ${SOT_CORE_CFLAGS})
+rosbuild_add_link_flags(ros_interpreter ${JRL_MAL_LDFLAGS}
+  ${DYNAMIC_GRAPH_LDFLAGS} ${DYNAMIC_GRAPH_PYTHON_LDFLAGS} ${SOT_CORE_LDFLAGS})
+target_link_libraries(ros_interpreter ros_bridge)
+target_link_libraries(ros_interpreter
+  ${JRL_MAL_LIBRARIES} ${DYNAMIC_GRAPH_LIBRARIES}
+  ${DYNAMIC_GRAPH_PYTHON_LIBRARIES} ${SOT_CORE_LIBRARIES})
 
+# Stand alone remote dynamic-graph Python interpreter.
+rosbuild_add_executable(interpreter src/interpreter.cpp)
+target_link_libraries(interpreter ros_interpreter)
 
 INSTALL(TARGETS ros_bridge DESTINATION lib)
 INSTALL(TARGETS ros_import DESTINATION lib)
 INSTALL(TARGETS ros_export DESTINATION lib)
 INSTALL(TARGETS ros_joint_state DESTINATION lib)
+INSTALL(TARGETS interpreter DESTINATION lib)
+INSTALL(TARGETS ros_interpreter DESTINATION bin)
 
 INCLUDE(cmake/python.cmake)
 
diff --git a/include/dynamic_graph_bridge/ros_interpreter.hh b/include/dynamic_graph_bridge/ros_interpreter.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ed6173e8fbba0c7d6059e2d1223c8f890c76ef6c
--- /dev/null
+++ b/include/dynamic_graph_bridge/ros_interpreter.hh
@@ -0,0 +1,38 @@
+#ifndef DYNAMIC_GRAPH_BRIDGE_INTERPRETER_HH
+# define DYNAMIC_GRAPH_BRIDGE_INTERPRETER_HH
+# include <ros/ros.h>
+# include <dynamic_graph_bridge/RunCommand.h>
+
+# include <dynamic-graph/python/interpreter.hh>
+
+namespace dynamicgraph
+{
+  /// \brief This class wraps the implementation of the runCommand
+  /// service.
+  ///
+  /// This takes as input a ROS node handle and do not handle the
+  /// callback so that the service behavior can be controlled from
+  /// the outside.
+  class Interpreter
+  {
+  public:
+    typedef boost::function<
+    bool (dynamic_graph_bridge::RunCommand::Request&,
+    	  dynamic_graph_bridge::RunCommand::Response&)>
+    runCommandCallback_t;
+
+    explicit Interpreter (ros::NodeHandle& nodeHandle);
+
+  protected:
+    /// \brief Run a Python command and return result, stderr and stdout.
+    bool runCommandCallback (dynamic_graph_bridge::RunCommand::Request& req,
+			     dynamic_graph_bridge::RunCommand::Response& res);
+
+  private:
+    python::Interpreter interpreter_;
+    ros::NodeHandle& nodeHandle_;
+    ros::ServiceServer runCommandSrv_;
+  };
+} // end of namespace dynamicgraph.
+
+#endif //! DYNAMIC_GRAPH_BRIDGE_INTERPRETER_HH
diff --git a/scripts/dgbridge-remote b/scripts/dgbridge-remote
new file mode 100755
index 0000000000000000000000000000000000000000..9aac7c2b591531cf0af4ff15072ec6db7f2d89c7
--- /dev/null
+++ b/scripts/dgbridge-remote
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+
+import roslib; roslib.load_manifest('dynamic_graph_bridge')
+import rospy
+
+import dynamic_graph_bridge.srv
+
+import sys
+import code
+from code import InteractiveConsole
+import readline
+
+class RosShell(InteractiveConsole):
+    def __init__(self):
+        self.cache = ""
+        InteractiveConsole.__init__(self)
+
+        rospy.loginfo('waiting for service...')
+        rospy.wait_for_service('run_command')
+        self.client = rospy.ServiceProxy(
+            'run_command', dynamic_graph_bridge.srv.RunCommand, True)
+
+
+    def runcode(self, code):
+        source = self.cache[:-1]
+        self.cache = ""
+        if source != "":
+            try:
+                if not self.client:
+                    print("Connection to remote server lost. Reconnecting...")
+                    self.client = rospy.ServiceProxy(
+                        'run_command', dynamic_graph_bridge.srv.RunCommand, True)
+                    return
+                response = self.client(str(source))
+                if response.stdout != "":
+                    print response.stdout[:-1]
+                if response.stderr != "":
+                    print response.stderr[:-1]
+                elif response.result != "None":
+                    print response.result
+            except rospy.ServiceException, e:
+                print("Connection to remote server lost. Reconnecting...")
+                self.client = rospy.ServiceProxy(
+                    'run_command', dynamic_graph_bridge.srv.RunCommand, True)
+
+    def push(self,line):
+        self.cache += line + "\n"
+        return InteractiveConsole.push(self,line)
+
+if __name__ == '__main__':
+    import optparse
+    manifest = roslib.manifest.load_manifest('dynamic_graph_bridge')
+    parser = optparse.OptionParser(
+        usage='\n\t%prog [options]',
+        version='%%prog %s' % manifest.version)
+    (options, args) = parser.parse_args(sys.argv[1:])
+
+    sh = RosShell()
+
+    if args[:]:
+        infile = args[0]
+        source = open(infile).read()
+        if not sh.client:
+            print("Connection to remote server has been lost.")
+            sys.exit(1)
+        response = sh.client(str(source))
+        if response.stdout != "":
+            print response.stdout[:-1]
+            if response.stderr != "":
+                print response.stderr[:-1]
+            elif response.result != "None":
+                print response.result
+    else:
+        sh.interact("Interacting with remote server.")
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9b4e8a9fcc2e997f654d6df3636b39c975088d0
--- /dev/null
+++ b/src/interpreter.cpp
@@ -0,0 +1,9 @@
+#include <dynamic_graph_bridge/ros_init.hh>
+#include <dynamic_graph_bridge/ros_interpreter.hh>
+
+int main ()
+{
+  ros::NodeHandle& nodeHandle = dynamicgraph::rosInit ();
+  dynamicgraph::Interpreter interpreter (nodeHandle);
+  ros::spin ();
+}
diff --git a/src/ros_interpreter.cpp b/src/ros_interpreter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fac3a751d0686b44a615840d57f39d648dd88a4a
--- /dev/null
+++ b/src/ros_interpreter.cpp
@@ -0,0 +1,27 @@
+#include "dynamic_graph_bridge/ros_interpreter.hh"
+
+namespace dynamicgraph
+{
+  static const int queueSize = 5;
+
+  Interpreter::Interpreter (ros::NodeHandle& nodeHandle)
+    : interpreter_ (),
+      nodeHandle_ (nodeHandle),
+      runCommandSrv_ ()
+  {
+    runCommandCallback_t runCommandCb =
+      boost::bind (&Interpreter::runCommandCallback, this, _1, _2);
+
+    runCommandSrv_ =
+      nodeHandle_.advertiseService ("run_command", runCommandCb);
+  }
+
+  bool
+  Interpreter::runCommandCallback(dynamic_graph_bridge::RunCommand::Request& req,
+				  dynamic_graph_bridge::RunCommand::Response& res)
+  {
+    interpreter_.python(req.input, res.result, res.stdout, res.stderr);
+    return true;
+  }
+} // end of namespace dynamicgraph.
+
diff --git a/srv/RunCommand.srv b/srv/RunCommand.srv
new file mode 100644
index 0000000000000000000000000000000000000000..4207e9bbe405bb5415530cb6863a0245bd5b525f
--- /dev/null
+++ b/srv/RunCommand.srv
@@ -0,0 +1,5 @@
+string input
+---
+string result
+string stdout
+string stderr