diff --git a/.asdf b/.asdf
new file mode 100644
index 0000000..e69de29
diff --git a/lua/timer.lua b/lua/timer.lua
index aae88a5..a360263 100644
--- a/lua/timer.lua
+++ b/lua/timer.lua
@@ -1,30 +1,161 @@
-local augroup = vim.api.nvim_create_augroup("ScratchBuffer", { clear = true })
+local TOML = require("toml")
 
+local augroup = vim.api.nvim_create_augroup("Timer", { clear = true })
+local focus_events = {}
+local clean_to = 1
+
+function trim(s)
+  return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+local function clean_from(from, events)
+  local to = 1
+  local clean_events = {}
+
+  -- coppy until from
+  for i = 1, from - 1, 1 do
+    table.insert(clean_events, events[i])
+  end
+
+  local last = {}
+  for i = from, #events, 1
+  do
+    local event = events[i]
+    local next_event = events[i + 1]
+
+
+    if next_event == nil then
+      --do nothing
+    elseif next_event.event == "gain" and event.event == "lose" then
+      if os.difftime(next_event.time, event.time) > 5 * 60 then
+        table.insert(clean_events, event)
+      end
+    end
+    if last == nil then
+      -- do nothing
+    elseif last.event == "lose" and event.event == "gain" then
+      if os.difftime(event.time, last.time) > 5 * 60 then
+        table.insert(clean_events, event)
+      end
+    end
+
+    last = event
+  end
+
+  return clean_events
+end
+
+local function time()
+  focus_events = clean_from(clean_to + 1, focus_events)
+  clean_to = #focus_events
+
+  local t = 0
+
+  local start = os.time()
+  for _, fe in pairs(focus_events) do
+    if fe.event == "gain" then
+      start = fe.time
+    else
+      t = t + os.difftime(fe.time, start)
+    end
+    if focus_events[#focus_events].event == "gain" then
+      t = t + os.difftime(os.time(), focus_events[#focus_events].time)
+    end
+  end
+  return t
+end
+
+local function log_time()
+  print(time())
+end
+
+local function log_time_table()
+  for i, e in pairs(focus_events) do
+    print(i, e.event, os.date("%H:%M:%S", e.time))
+  end
+end
 
 local function focus_gained()
   print("Huiii Fokus")
+
+  table.insert(focus_events, {
+    time = os.time(),
+    event = "gain",
+  })
 end
 
 local function focus_lost()
   print("Hokus pokus fort ist der fokus")
+
+  table.insert(focus_events, {
+    time = os.time(),
+    event = "lose",
+  })
 end
 
-local function main()
-  print("Hello from our plugin")
-  print(os.time())
+local function persist()
+  local filename = ".timer.toml"
+  local username = trim(os.getenv("USER")) .. "_at_" .. trim(io.popen("hostname -s"):read("*a"))
+  local today = os.date("%y-%m-%d", os.time())
+  local table = {}
+
+  local file = io.open(filename, "r")
+
+  -- if file exists read
+  if file ~= nil then
+    table = TOML.parse(file:read("*a"))
+    file:close()
+  end
+
+  -- write time to table
+  if table[today] ~= nil and table[today][username] ~= nil then
+    table[today][username] = table[today][username] + time()
+  else
+    if table[today] == nil then
+      table[today] = {}
+    end
+    table[today][username] = time()
+  end
+
+  -- write table to file
+  file = io.open(filename, "w")
+  if file == nil then
+    error("can't write to .timer file")
+    return
+  end
+
+  file:write("## dates and their corresponding seconds been here :)\n", TOML.encode(table), "\n")
+  file.close()
+
+  --reset timer
+  clean_to = 1
+  focus_events = {}
+  focus_gained()
 end
+
 local function setup()
   vim.api.nvim_create_autocmd("VimEnter",
-    { group = augroup, desc = "Set a fennel scratch buffer on load", once = true, callback = main })
+    { group = augroup, desc = "Start Timer", once = true, callback = focus_gained })
+  vim.api.nvim_create_autocmd("ExitPre",
+    { group = augroup, desc = "Persist timer", once = true, callback = persist })
+  vim.api.nvim_create_autocmd("FocusGained", { group = augroup, callback = focus_gained })
+  vim.api.nvim_create_autocmd("FocusLost", { group = augroup, callback = focus_lost })
+
   vim.api.nvim_create_user_command(
-    'Timer',                  -- The name of the command (accessible via :TimerStart)
-    function()
-      print("Timer started!") -- The function executed when the command is called
-    end,
-    { nargs = 0 }             -- No arguments for this command (you can configure this later)
+    'Timer',      -- The name of the command (accessible via :TimerStart)
+    log_time,
+    { nargs = 0 } -- No arguments for this command (you can configure this later)
+  )
+  vim.api.nvim_create_user_command(
+    'TimerLog',   -- The name of the command (accessible via :TimerStart)
+    log_time_table,
+    { nargs = 0 } -- No arguments for this command (you can configure this later)
+  )
+  vim.api.nvim_create_user_command(
+    'TimerSave',  -- The name of the command (accessible via :TimerStart)
+    persist,
+    { nargs = 0 } -- No arguments for this command (you can configure this later)
   )
-  vim.api.nvim_create_autocmd("FocusGained", { callback = focus_gained })
-  vim.api.nvim_create_autocmd("FocusLost", { callback = focus_lost })
 end
 
 return { setup = setup }
diff --git a/lua/toml.lua b/lua/toml.lua
new file mode 100644
index 0000000..b1a34bc
--- /dev/null
+++ b/lua/toml.lua
@@ -0,0 +1,644 @@
+-- source: https://github.com/jonstoler/lua-toml/blob/master/toml.lua
+local TOML = {
+  -- denotes the current supported TOML version
+  version = 0.40,
+
+  -- sets whether the parser should follow the TOML spec strictly
+  -- currently, no errors are thrown for the following rules if strictness is turned off:
+  --   tables having mixed keys
+  --   redefining a table
+  --   redefining a key within a table
+  strict = true,
+}
+
+-- converts TOML data into a lua table
+TOML.parse = function(toml, options)
+  options = options or {}
+  local strict = (options.strict ~= nil and options.strict or TOML.strict)
+
+  -- the official TOML definition of whitespace
+  local ws = "[\009\032]"
+
+  -- the official TOML definition of newline
+  local nl = "[\10"
+  do
+    local crlf = "\13\10"
+    nl = nl .. crlf
+  end
+  nl = nl .. "]"
+
+  -- stores text data
+  local buffer = ""
+
+  -- the current location within the string to parse
+  local cursor = 1
+
+  -- the output table
+  local out = {}
+
+  -- the current table to write to
+  local obj = out
+
+  -- returns the next n characters from the current position
+  local function char(n)
+    n = n or 0
+    return toml:sub(cursor + n, cursor + n)
+  end
+
+  -- moves the current position forward n (default: 1) characters
+  local function step(n)
+    n = n or 1
+    cursor = cursor + n
+  end
+
+  -- move forward until the next non-whitespace character
+  local function skipWhitespace()
+    while (char():match(ws)) do
+      step()
+    end
+  end
+
+  -- remove the (Lua) whitespace at the beginning and end of a string
+  local function trim(str)
+    return str:gsub("^%s*(.-)%s*$", "%1")
+  end
+
+  -- divide a string into a table around a delimiter
+  local function split(str, delim)
+    if str == "" then return {} end
+    local result = {}
+    local append = delim
+    if delim:match("%%") then
+      append = delim:gsub("%%", "")
+    end
+    for match in (str .. append):gmatch("(.-)" .. delim) do
+      table.insert(result, match)
+    end
+    return result
+  end
+
+  -- produce a parsing error message
+  -- the error contains the line number of the current position
+  local function err(message, strictOnly)
+    if not strictOnly or (strictOnly and strict) then
+      local line = 1
+      local c = 0
+      for l in toml:gmatch("(.-)" .. nl) do
+        c = c + l:len()
+        if c >= cursor then
+          break
+        end
+        line = line + 1
+      end
+      error("TOML: " .. message .. " on line " .. line .. ".", 4)
+    end
+  end
+
+  -- prevent infinite loops by checking whether the cursor is
+  -- at the end of the document or not
+  local function bounds()
+    return cursor <= toml:len()
+  end
+
+  local function parseString()
+    local quoteType = char() -- should be single or double quote
+
+    -- this is a multiline string if the next 2 characters match
+    local multiline = (char(1) == char(2) and char(1) == char())
+
+    -- buffer to hold the string
+    local str = ""
+
+    -- skip the quotes
+    step(multiline and 3 or 1)
+
+    while (bounds()) do
+      if multiline and char():match(nl) and str == "" then
+        -- skip line break line at the beginning of multiline string
+        step()
+      end
+
+      -- keep going until we encounter the quote character again
+      if char() == quoteType then
+        if multiline then
+          if char(1) == char(2) and char(1) == quoteType then
+            step(3)
+            break
+          end
+        else
+          step()
+          break
+        end
+      end
+
+      if char():match(nl) and not multiline then
+        err("Single-line string cannot contain line break")
+      end
+
+      -- if we're in a double-quoted string, watch for escape characters!
+      if quoteType == '"' and char() == "\\" then
+        if multiline and char(1):match(nl) then
+          -- skip until first non-whitespace character
+          step(1) -- go past the line break
+          while (bounds()) do
+            if not char():match(ws) and not char():match(nl) then
+              break
+            end
+            step()
+          end
+        else
+          -- all available escape characters
+          local escape = {
+            b = "\b",
+            t = "\t",
+            n = "\n",
+            f = "\f",
+            r = "\r",
+            ['"'] = '"',
+            ["\\"] = "\\",
+          }
+          -- utf function from http://stackoverflow.com/a/26071044
+          -- converts \uXXX into actual unicode
+          local function utf(char)
+            local bytemarkers = { { 0x7ff, 192 }, { 0xffff, 224 }, { 0x1fffff, 240 } }
+            if char < 128 then return string.char(char) end
+            local charbytes = {}
+            for bytes, vals in pairs(bytemarkers) do
+              if char <= vals[1] then
+                for b = bytes + 1, 2, -1 do
+                  local mod = char % 64
+                  char = (char - mod) / 64
+                  charbytes[b] = string.char(128 + mod)
+                end
+                charbytes[1] = string.char(vals[2] + char)
+                break
+              end
+            end
+            return table.concat(charbytes)
+          end
+
+          if escape[char(1)] then
+            -- normal escape
+            str = str .. escape[char(1)]
+            step(2) -- go past backslash and the character
+          elseif char(1) == "u" then
+            -- utf-16
+            step()
+            local uni = char(1) .. char(2) .. char(3) .. char(4)
+            step(5)
+            uni = tonumber(uni, 16)
+            if (uni >= 0 and uni <= 0xd7ff) and not (uni >= 0xe000 and uni <= 0x10ffff) then
+              str = str .. utf(uni)
+            else
+              err("Unicode escape is not a Unicode scalar")
+            end
+          elseif char(1) == "U" then
+            -- utf-32
+            step()
+            local uni = char(1) .. char(2) .. char(3) .. char(4) .. char(5) .. char(6) .. char(7) .. char(8)
+            step(9)
+            uni = tonumber(uni, 16)
+            if (uni >= 0 and uni <= 0xd7ff) and not (uni >= 0xe000 and uni <= 0x10ffff) then
+              str = str .. utf(uni)
+            else
+              err("Unicode escape is not a Unicode scalar")
+            end
+          else
+            err("Invalid escape")
+          end
+        end
+      else
+        -- if we're not in a double-quoted string, just append it to our buffer raw and keep going
+        str = str .. char()
+        step()
+      end
+    end
+
+    return { value = str, type = "string" }
+  end
+
+  local function parseNumber()
+    local num = ""
+    local exp
+    local date = false
+    while (bounds()) do
+      if char():match("[%+%-%.eE_0-9]") then
+        if not exp then
+          if char():lower() == "e" then
+            -- as soon as we reach e or E, start appending to exponent buffer instead of
+            -- number buffer
+            exp = ""
+          elseif char() ~= "_" then
+            num = num .. char()
+          end
+        elseif char():match("[%+%-0-9]") then
+          exp = exp .. char()
+        else
+          err("Invalid exponent")
+        end
+      elseif char():match(ws) or char() == "#" or char():match(nl) or char() == "," or char() == "]" or char() == "}" then
+        break
+      elseif char() == "T" or char() == "Z" then
+        -- parse the date (as a string, since lua has no date object)
+        date = true
+        while (bounds()) do
+          if char() == "," or char() == "]" or char() == "#" or char():match(nl) or char():match(ws) then
+            break
+          end
+          num = num .. char()
+          step()
+        end
+      else
+        err("Invalid number")
+      end
+      step()
+    end
+
+    if date then
+      return { value = num, type = "date" }
+    end
+
+    local float = false
+    if num:match("%.") then float = true end
+
+    exp = exp and tonumber(exp) or 0
+    num = tonumber(num)
+
+    if not float then
+      return {
+        -- lua will automatically convert the result
+        -- of a power operation to a float, so we have
+        -- to convert it back to an int with math.floor
+        value = math.floor(num * 10 ^ exp),
+        type = "int",
+      }
+    end
+
+    return { value = num * 10 ^ exp, type = "float" }
+  end
+
+  local parseArray, getValue
+
+  function parseArray()
+    step() -- skip [
+    skipWhitespace()
+
+    local arrayType
+    local array = {}
+
+    while (bounds()) do
+      if char() == "]" then
+        break
+      elseif char():match(nl) then
+        -- skip
+        step()
+        skipWhitespace()
+      elseif char() == "#" then
+        while (bounds() and not char():match(nl)) do
+          step()
+        end
+      else
+        -- get the next object in the array
+        local v = getValue()
+        if not v then break end
+
+        -- set the type if it hasn't been set before
+        if arrayType == nil then
+          arrayType = v.type
+        elseif arrayType ~= v.type then
+          err("Mixed types in array", true)
+        end
+
+        array = array or {}
+        table.insert(array, v.value)
+
+        if char() == "," then
+          step()
+        end
+        skipWhitespace()
+      end
+    end
+    step()
+
+    return { value = array, type = "array" }
+  end
+
+  local function parseInlineTable()
+    step() -- skip opening brace
+
+    local buffer = ""
+    local quoted = false
+    local tbl = {}
+
+    while bounds() do
+      if char() == "}" then
+        break
+      elseif char() == "'" or char() == '"' then
+        buffer = parseString().value
+        quoted = true
+      elseif char() == "=" then
+        if not quoted then
+          buffer = trim(buffer)
+        end
+
+        step() -- skip =
+        skipWhitespace()
+
+        if char():match(nl) then
+          err("Newline in inline table")
+        end
+
+        local v = getValue().value
+        tbl[buffer] = v
+
+        skipWhitespace()
+
+        if char() == "," then
+          step()
+        elseif char():match(nl) then
+          err("Newline in inline table")
+        end
+
+        quoted = false
+        buffer = ""
+      else
+        buffer = buffer .. char()
+        step()
+      end
+    end
+    step() -- skip closing brace
+
+    return { value = tbl, type = "array" }
+  end
+
+  local function parseBoolean()
+    local v
+    if toml:sub(cursor, cursor + 3) == "true" then
+      step(4)
+      v = { value = true, type = "boolean" }
+    elseif toml:sub(cursor, cursor + 4) == "false" then
+      step(5)
+      v = { value = false, type = "boolean" }
+    else
+      err("Invalid primitive")
+    end
+
+    skipWhitespace()
+    if char() == "#" then
+      while (not char():match(nl)) do
+        step()
+      end
+    end
+
+    return v
+  end
+
+  -- figure out the type and get the next value in the document
+  function getValue()
+    if char() == '"' or char() == "'" then
+      return parseString()
+    elseif char():match("[%+%-0-9]") then
+      return parseNumber()
+    elseif char() == "[" then
+      return parseArray()
+    elseif char() == "{" then
+      return parseInlineTable()
+    else
+      return parseBoolean()
+    end
+    -- date regex (for possible future support):
+    -- %d%d%d%d%-[0-1][0-9]%-[0-3][0-9]T[0-2][0-9]%:[0-6][0-9]%:[0-6][0-9][Z%:%+%-%.0-9]*
+  end
+
+  -- track whether the current key was quoted or not
+  local quotedKey = false
+
+  -- parse the document!
+  while (cursor <= toml:len()) do
+    -- skip comments and whitespace
+    if char() == "#" then
+      while (not char():match(nl)) do
+        step()
+      end
+    end
+
+    if char():match(nl) then
+      -- skip
+    end
+
+    if char() == "=" then
+      step()
+      skipWhitespace()
+
+      -- trim key name
+      buffer = trim(buffer)
+
+      if buffer:match("^[0-9]*$") and not quotedKey then
+        buffer = tonumber(buffer)
+      end
+
+      if buffer == "" and not quotedKey then
+        err("Empty key name")
+      end
+
+      local v = getValue()
+      if v then
+        -- if the key already exists in the current object, throw an error
+        if obj[buffer] then
+          err('Cannot redefine key "' .. buffer .. '"', true)
+        end
+        obj[buffer] = v.value
+      end
+
+      -- clear the buffer
+      buffer = ""
+      quotedKey = false
+
+      -- skip whitespace and comments
+      skipWhitespace()
+      if char() == "#" then
+        while (bounds() and not char():match(nl)) do
+          step()
+        end
+      end
+
+      -- if there is anything left on this line after parsing a key and its value,
+      -- throw an error
+      if not char():match(nl) and cursor < toml:len() then
+        err("Invalid primitive")
+      end
+    elseif char() == "[" then
+      buffer = ""
+      step()
+      local tableArray = false
+
+      -- if there are two brackets in a row, it's a table array!
+      if char() == "[" then
+        tableArray = true
+        step()
+      end
+
+      obj = out
+
+      local function processKey(isLast)
+        isLast = isLast or false
+        buffer = trim(buffer)
+
+        if not quotedKey and buffer == "" then
+          err("Empty table name")
+        end
+
+        if isLast and obj[buffer] and not tableArray and #obj[buffer] > 0 then
+          err("Cannot redefine table", true)
+        end
+
+        -- set obj to the appropriate table so we can start
+        -- filling it with values!
+        if tableArray then
+          -- push onto cache
+          if obj[buffer] then
+            obj = obj[buffer]
+            if isLast then
+              table.insert(obj, {})
+            end
+            obj = obj[#obj]
+          else
+            obj[buffer] = {}
+            obj = obj[buffer]
+            if isLast then
+              table.insert(obj, {})
+              obj = obj[1]
+            end
+          end
+        else
+          obj[buffer] = obj[buffer] or {}
+          obj = obj[buffer]
+        end
+      end
+
+      while (bounds()) do
+        if char() == "]" then
+          if tableArray then
+            if char(1) ~= "]" then
+              err("Mismatching brackets")
+            else
+              step() -- skip inside bracket
+            end
+          end
+          step() -- skip outside bracket
+
+          processKey(true)
+          buffer = ""
+          break
+        elseif char() == '"' or char() == "'" then
+          buffer = parseString().value
+          quotedKey = true
+        elseif char() == "." then
+          step() -- skip period
+          processKey()
+          buffer = ""
+        else
+          buffer = buffer .. char()
+          step()
+        end
+      end
+
+      buffer = ""
+      quotedKey = false
+    elseif (char() == '"' or char() == "'") then
+      -- quoted key
+      buffer = parseString().value
+      quotedKey = true
+    end
+
+    buffer = buffer .. (char():match(nl) and "" or char())
+    step()
+  end
+
+  return out
+end
+
+TOML.encode = function(tbl)
+  local toml = ""
+
+  local cache = {}
+
+  local function parse(tbl)
+    for k, v in pairs(tbl) do
+      if type(v) == "boolean" then
+        toml = toml .. k .. " = " .. tostring(v) .. "\n"
+      elseif type(v) == "number" then
+        toml = toml .. k .. " = " .. tostring(v) .. "\n"
+      elseif type(v) == "string" then
+        local quote = '"'
+        v = v:gsub("\\", "\\\\")
+
+        -- if the string has any line breaks, make it multiline
+        if v:match("^\n(.*)$") then
+          quote = quote:rep(3)
+          v = "\\n" .. v
+        elseif v:match("\n") then
+          quote = quote:rep(3)
+        end
+
+        v = v:gsub("\b", "\\b")
+        v = v:gsub("\t", "\\t")
+        v = v:gsub("\f", "\\f")
+        v = v:gsub("\r", "\\r")
+        v = v:gsub('"', '\\"')
+        v = v:gsub("/", "\\/")
+        toml = toml .. k .. " = " .. quote .. v .. quote .. "\n"
+      elseif type(v) == "table" then
+        local array, arrayTable = true, true
+        local first = {}
+        for kk, vv in pairs(v) do
+          if type(kk) ~= "number" then array = false end
+          if type(vv) ~= "table" then
+            v[kk] = nil
+            first[kk] = vv
+            arrayTable = false
+          end
+        end
+
+        if array then
+          if arrayTable then
+            -- double bracket syntax go!
+            table.insert(cache, k)
+            for kk, vv in pairs(v) do
+              toml = toml .. "[[" .. table.concat(cache, ".") .. "]]\n"
+              for k3, v3 in pairs(vv) do
+                if type(v3) ~= "table" then
+                  vv[k3] = nil
+                  first[k3] = v3
+                end
+              end
+              parse(first)
+              parse(vv)
+            end
+            table.remove(cache)
+          else
+            -- plain ol boring array
+            toml = toml .. k .. " = [\n"
+            for kk, vv in pairs(first) do
+              toml = toml .. tostring(vv) .. ",\n"
+            end
+            toml = toml .. "]\n"
+          end
+        else
+          -- just a key/value table, folks
+          table.insert(cache, k)
+          toml = toml .. "[" .. table.concat(cache, ".") .. "]\n"
+          parse(first)
+          parse(v)
+          table.remove(cache)
+        end
+      end
+    end
+  end
+
+  parse(tbl)
+
+  return toml:sub(1, -2)
+end
+
+return TOML
diff --git a/test.lua b/test.lua
new file mode 100644
index 0000000..58cee16
--- /dev/null
+++ b/test.lua
@@ -0,0 +1,4 @@
+local username = os.getenv("USER")
+local hostname = io.popen("hostname -s"):read("*a")
+print(username)
+print(hostname)