diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for nuxeo
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2018, Alexandre Peyroux
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Alexandre Peyroux nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/nuxeo.cabal b/nuxeo.cabal
new file mode 100644
--- /dev/null
+++ b/nuxeo.cabal
@@ -0,0 +1,32 @@
+-- Initial nuxeo.cabal generated by cabal init.  For further documentation,
+--  see http://haskell.org/cabal/users-guide/
+
+name:                nuxeo
+version:             0.1.0.0
+synopsis:            Nuxeo
+description:         Nuxeo
+license:             BSD3
+license-file:        LICENSE
+author:              Alexandre Peyroux
+maintainer:          alex@xn--wxa.email
+-- copyright:
+category:            System
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+library
+  -- exposed-modules:
+  -- other-modules:
+  -- other-extensions:
+  exposed-modules:     Nuxeo.Log
+  ghc-options:         -Wall
+  build-depends:       base >=4.10 && <4.11
+                     , attoparsec
+                     , bytestring
+                     , conduit
+                     , conduit-extra
+                     , text
+                     , time
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Nuxeo/Log.hs b/src/Nuxeo/Log.hs
new file mode 100644
--- /dev/null
+++ b/src/Nuxeo/Log.hs
@@ -0,0 +1,81 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Nuxeo.Log (
+  NuxeoTypeLog (..)
+  , NuxeoLogEntry (..)
+  , parseNuxeoLog
+  ) where
+
+import           Control.Applicative
+import           Data.Attoparsec.ByteString.Char8
+import           Data.Attoparsec.Combinator
+import           Data.Conduit
+import           Data.Conduit.Attoparsec
+import           Data.Conduit.Binary
+import qualified Data.Text as T
+import           Data.Time
+
+type Verbose = Bool
+
+data NuxeoTypeLog = Debug | Error | Warning | Info deriving (Show, Read, Eq)
+
+data NuxeoLogEntry = NuxeoLogEntry {
+  nuxeoLogEntryDthr :: LocalTime
+  , nuxeoLogEntryType :: NuxeoTypeLog
+  , nuxeoLogEntrySection :: T.Text
+  , nuxeoLogEntryAction :: T.Text
+  , nuxeoLogEntryLog :: T.Text
+  } deriving Show
+
+type NuxeoLog = [NuxeoLogEntry]
+
+-- |Parse Nuxeo server.log
+-- > logs <- parseNuxeoLog v "/opt/nuxeo-data/log/server.log"
+-- > filter (\l -> (nuxeoLogEntryType l == Error)
+-- >            || (nuxeoLogEntryType l == Warning)) logs
+parseNuxeoLog :: Verbose -> FilePath -> IO NuxeoLog
+parseNuxeoLog v logpath = runConduitRes $ sourceFile logpath .| sinkParser (nuxeoLogParser v)
+
+nuxeoLogParser :: Verbose -> Parser NuxeoLog
+nuxeoLogParser v = many $ (nuxeoLogEntryParser v <* endOfLine)
+
+nuxeoLogEntryParser :: Verbose -> Parser NuxeoLogEntry
+nuxeoLogEntryParser v = do
+  letime <- timeParser
+  letype <- space *> nuxeoTypeLogParser
+  section <- space *> nuxeoLogEntrySectionParser
+  action <- space *> nuxeoLogEntryActionParser
+  nuxeolog <- case v of
+    True -> space *> manyTill' anyChar (try $ lookAhead $ char '\n' *> timeParser)
+    False -> space *> manyTill' anyChar (try $ lookAhead $ char '\n')
+  return $ NuxeoLogEntry letime letype section action (T.pack nuxeolog)
+
+nuxeoTypeLogParser :: Parser NuxeoTypeLog
+nuxeoTypeLogParser = (string "ERROR" *> return Error)
+                     <|> (string "DEBUG" *> return Debug)
+                     <|> (string "WARN" *> return Warning)
+                     <|> (string "INFO" *> return Info)
+                     <|> fail "Invalid NuxeoTypeLog"
+
+nuxeoLogEntrySectionParser :: Parser T.Text
+nuxeoLogEntrySectionParser = char '[' *> manyTill' anyChar (char ']')
+  <|> fail "Oops parse section" >>= return . T.pack
+
+nuxeoLogEntryActionParser :: Parser T.Text
+nuxeoLogEntryActionParser = char '[' *> manyTill' anyChar (char ']')
+  <|> fail "Oops parse action" >>= return . T.pack
+
+timeParser :: Parser LocalTime
+timeParser = do
+  y  <- count 4 digit
+  mm <- char '-' *> count 2 digit
+  d  <- char '-' *> count 2 digit
+  h  <- char ' ' *> count 2 digit
+  m  <- char ':' *> count 2 digit
+  s  <- char ':' *> count 2 digit
+        *> char ','
+        *> count 3 digit
+  return $
+    LocalTime { localDay = fromGregorian (read y) (read mm) (read d)
+              , localTimeOfDay = TimeOfDay (read h) (read m) (read s)
+                }
