diff --git a/bindings/pyroot/CMakeLists.txt b/bindings/pyroot/CMakeLists.txt
index 280ea599d4fe33ebc06c7a06ad1a46b6868d214e..a8b5c06db051b234909df503b2a1f6fb247cd819 100644
--- a/bindings/pyroot/CMakeLists.txt
+++ b/bindings/pyroot/CMakeLists.txt
@@ -17,6 +17,8 @@ if(WIN32)
                 -include:_G__cpp_setupG__MathCore)
 endif()
 ROOT_LINKER_LIBRARY(PyROOT *.cxx G__PyROOT.cxx LIBRARIES Core Net Tree MathCore Rint ${PYTHON_LIBRARIES})
+ROOT_LINKER_LIBRARY(JupyROOT ../JupyROOT/src/*.cxx LIBRARIES Core)
+
 
 if(MSVC)
   add_custom_command(TARGET PyROOT POST_BUILD
diff --git a/bindings/pyroot/JupyROOT/src/IOHandler.cxx b/bindings/pyroot/JupyROOT/src/IOHandler.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4a7e0550c183102a4542945e6437f177c779b5ba
--- /dev/null
+++ b/bindings/pyroot/JupyROOT/src/IOHandler.cxx
@@ -0,0 +1,201 @@
+// Author: Danilo Piparo, Omar Zapata   16/12/2015
+
+#include <string>
+
+class JupyROOTExecutorHandler {
+private:
+   bool fCapturing;
+   std::string fStdoutpipe;
+   std::string fStderrpipe;
+   int fStdout_pipe[2];
+   int fStderr_pipe[2];
+   int fSaved_stderr;
+   int fSaved_stdout;
+public:
+   JupyROOTExecutorHandler();
+   void Poll();
+   void InitCapture();
+   void EndCapture();
+   void Clear();
+   std::string& GetStdout();
+   std::string& GetStderr();
+};
+
+bool JupyROOTExecutorImpl(const char *code);
+bool JupyROOTDeclarerImpl(const char *code);
+
+
+//------------------------------------------------------------------------------
+
+#include <unistd.h>
+#include <fcntl.h>
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE       1024
+#endif
+#ifndef F_SETPIPE_SZ
+#define F_SETPIPE_SZ    (F_LINUX_SPECIFIC_BASE + 7)
+#endif
+
+constexpr long MAX_PIPE_SIZE = 1048575;
+
+JupyROOTExecutorHandler::JupyROOTExecutorHandler()
+{
+   fCapturing = false;
+}
+
+static void PollImpl(FILE* stdStream, int* pipeHandle, std::string& pipeContent)
+{
+   int buf_read;
+   char ch;
+   fflush(stdStream);
+   while (true)          {
+      buf_read = read(pipeHandle[0], &ch, 1);
+      if (buf_read == 1) {
+         pipeContent += ch;
+      } else break;
+   }
+}
+
+void JupyROOTExecutorHandler::Poll()
+{
+   PollImpl(stdout, fStdout_pipe, fStdoutpipe);
+   PollImpl(stderr, fStderr_pipe, fStderrpipe);
+}
+
+static void InitCaptureImpl(int& savedStdStream, int* pipeHandle)
+{
+   savedStdStream = dup(STDOUT_FILENO);
+   if (pipe(pipeHandle) != 0) {
+      return;
+   }
+   long flags_stdout = fcntl(pipeHandle[0], F_GETFL);
+   flags_stdout |= O_NONBLOCK;
+   fcntl(pipeHandle[0], F_SETFL, flags_stdout);
+   fcntl(pipeHandle[0], F_SETPIPE_SZ, MAX_PIPE_SIZE);
+   dup2(pipeHandle[1], STDOUT_FILENO);
+   close(pipeHandle[1]);
+}
+
+void JupyROOTExecutorHandler::InitCapture()
+{
+   if (!fCapturing)  {
+      InitCaptureImpl(fSaved_stdout, fStdout_pipe);
+      InitCaptureImpl(fSaved_stderr, fStderr_pipe);
+   }
+}
+
+void JupyROOTExecutorHandler::EndCapture()
+{
+   if (fCapturing)  {
+      Poll();
+      dup2(fSaved_stdout, STDOUT_FILENO);
+      dup2(fSaved_stderr, STDERR_FILENO);
+   }
+   fCapturing = false;
+}
+
+std::string &JupyROOTExecutorHandler::GetStdout()
+{
+   return fStdoutpipe;
+}
+
+std::string &JupyROOTExecutorHandler::GetStderr()
+{
+   return fStderrpipe;
+}
+
+void JupyROOTExecutorHandler::Clear()
+{
+   fStdoutpipe = "";
+   fStderrpipe = "";
+}
+
+#include "TInterpreter.h"
+
+bool JupyROOTExecutorImpl(const char *code)
+{
+   auto status = false;
+   try {
+      if (gInterpreter->ProcessLine(code))    {
+         status = true;
+      }
+   }
+   catch(...) {
+      status = true;
+   }
+   return status;
+}
+
+bool JupyROOTDeclarerImpl(const char *code)
+{
+   bool status = false;
+   try {
+      if (gInterpreter->Declare(code)) {
+         status = true;
+      }
+   }
+   catch(...) {
+      status = true;
+   }
+   return status;
+}
+
+
+JupyROOTExecutorHandler *JupyROOTExecutorHandler_ptr = nullptr;
+
+extern "C" {
+
+   int JupyROOTExecutor(const char *code)
+   {
+      return JupyROOTExecutorImpl(code);
+   }
+   int JupyROOTDeclarer(const char *code)
+   {
+      return JupyROOTDeclarerImpl(code);
+   }
+
+   void JupyROOTExecutorHandler_Clear()
+   {
+      JupyROOTExecutorHandler_ptr->Clear();
+   }
+
+   void JupyROOTExecutorHandler_Ctor()
+   {
+      JupyROOTExecutorHandler_ptr = new JupyROOTExecutorHandler();
+   }
+
+   void JupyROOTExecutorHandler_Poll()
+   {
+      JupyROOTExecutorHandler_ptr->Poll();
+   }
+
+   void JupyROOTExecutorHandler_EndCapture()
+   {
+      JupyROOTExecutorHandler_ptr->EndCapture();
+   }
+
+   void JupyROOTExecutorHandler_InitCapture()
+   {
+      JupyROOTExecutorHandler_ptr->InitCapture();
+   }
+
+   const char *JupyROOTExecutorHandler_GetStdout()
+   {
+      auto out = JupyROOTExecutorHandler_ptr->GetStdout();
+      if (out.empty()) return 0;
+      return out.c_str();
+   }
+
+   const char *JupyROOTExecutorHandler_GetStderr()
+   {
+      auto out = JupyROOTExecutorHandler_ptr->GetStderr();
+      if (out.empty()) return 0;
+      return out.c_str();
+   }
+
+   void JupyROOTExecutorHandler_Dtor()
+   {
+      delete JupyROOTExecutorHandler_ptr;
+   }
+
+}