diff --git a/lua/oz.lua b/lua/oz.lua
index 4108824..b725888 100644
--- a/lua/oz.lua
+++ b/lua/oz.lua
@@ -19,8 +19,6 @@ local M = {}
 M.opts = opts
 
 ---@param args Options?
--- you can define your setup function here. Usually configurations can be merged, accepting outside params and
--- you can also put some validation here for those.
 function M.setup(args)
   M.opts = vim.tbl_deep_extend("force", M.opts, args or {})
 end
@@ -94,4 +92,17 @@ function M.restart_engine()
   engine.restart(M)
 end
 
+----- LOGS
+function M.open_log()
+  engine.openlogs()
+end
+
+function M.close_log()
+  engine.closelogs()
+end
+
+function M.toogle_log()
+  engine.tooglelogs()
+end
+
 return M
diff --git a/lua/oz/engine.lua b/lua/oz/engine.lua
index ffcd213..831c7ff 100644
--- a/lua/oz/engine.lua
+++ b/lua/oz/engine.lua
@@ -1,3 +1,5 @@
+local LogBuf = require("oz.log")
+
 ---@class OzEngine
 local M = {}
 
@@ -18,11 +20,12 @@ local EC = {
 ---@param port string
 function EC:spinsup_compiler(port)
   local command = { "socat", "-", string.format("TCP:localhost:%s", port) }
-  -- vim.notify(string.format("TCP:localhost:%s", port), vim.log.levels.WARN, { title = "oz.nvim" })
 
   self.compiler.pid = vim.fn.jobstart(command, {
-    ---@param data string
-    on_stdout = function(_, data, _) end,
+    ---@param data string[]
+    on_stdout = function(_, data, _)
+      LogBuf:push(data)
+    end,
     on_stderr = function(_, data, _)
       vim.notify(table.concat(data, "\n"), vim.log.levels.WARN, { title = "oz.nvim" })
     end,
@@ -151,4 +154,16 @@ function M.restart(instance)
   EC:start(instance)
 end
 
+function M.openlogs()
+  LogBuf:open_log()
+end
+
+function M.closelogs()
+  LogBuf:close_log()
+end
+
+function M.tooglelogs()
+  LogBuf:toogle_log()
+end
+
 return M
diff --git a/lua/oz/log.lua b/lua/oz/log.lua
new file mode 100644
index 0000000..96008d2
--- /dev/null
+++ b/lua/oz/log.lua
@@ -0,0 +1,73 @@
+---@class LogBuffer
+local LogBuf = {
+  ---@type integer
+  nr = vim.api.nvim_create_buf(true, false),
+  ---@type string[]
+  content = {},
+  ---@type number
+  max_content_lines = 500,
+  win = {
+    open = false,
+    ---@type number
+    id = nil,
+  },
+}
+
+function LogBuf:clear_buf()
+  vim.api.nvim_buf_set_lines(self.nr, 0, -1, false, {})
+end
+
+---@param lines string[]
+function LogBuf:set_buf_lines(lines)
+  self:clear_buf()
+  vim.api.nvim_buf_set_lines(self.nr, 0, -1, false, lines)
+end
+
+---@param lines string[]
+function LogBuf:push(lines)
+  local total_lines = #self.content + #lines
+  if total_lines <= self.max_content_lines then
+    for _, line in ipairs(lines) do
+      table.insert(self.content, line)
+    end
+  else
+    local excess_lines = total_lines - self.max_content_lines
+    for i = 1, excess_lines do
+      table.remove(self.content, 1)
+    end
+    for _, line in ipairs(lines) do
+      table.insert(self.content, line)
+    end
+  end
+
+  self:set_buf_lines(self.content)
+end
+
+function LogBuf:open_log()
+  if self.win.open ~= true then
+    self.win.id = vim.api.nvim_open_win(self.nr, false, {
+      split = "left",
+      title = "[oz.nvim::Logger]",
+      anchor = "SW",
+    })
+    self.win.open = true
+  end
+end
+
+function LogBuf:close_log()
+  if self.win.open ~= false then
+    vim.api.nvim_win_close(self.win.id, true)
+    self.win.id = nil
+    self.win.open = false
+  end
+end
+
+function LogBuf:toogle_log()
+  if self.win.open then
+    self:close_log()
+  else
+    self:open_log()
+  end
+end
+
+return LogBuf
diff --git a/plugin/oz.lua b/plugin/oz.lua
index 1d1eeb2..a1e25b5 100644
--- a/plugin/oz.lua
+++ b/plugin/oz.lua
@@ -17,6 +17,18 @@ vim.api.nvim_create_autocmd({ "BufEnter" }, {
       oz.restart_engine()
     end, {})
 
+    vim.api.nvim_create_user_command("OzOpenLog", function()
+      oz.open_log()
+    end, {})
+
+    vim.api.nvim_create_user_command("OzCloseLog", function()
+      oz.open_log()
+    end, {})
+
+    vim.api.nvim_create_user_command("OzToggleLog", function()
+      oz.toogle_log()
+    end, {})
+
     vim.keymap.set("v", oz.opts.keymaps.feed_selection_mapping, function()
       oz.feed_selection(args.buf)
     end, { desc = "Feed the current selection into the oz engine" })