diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Timur Rubeko (c) 2015
+
+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 Timur Rubeko 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/app/FromGit.hs b/app/FromGit.hs
new file mode 100644
--- /dev/null
+++ b/app/FromGit.hs
@@ -0,0 +1,17 @@
+module Main where
+
+import System.Environment
+import Data.Either.Utils
+
+import Config
+import Git
+import CLI
+
+main :: IO ()
+main = do
+  args <- getArgs
+  user <- getGitUser
+  config <- forceEither <$> readConfig
+  gitLog <- getGitLog config user args
+  let workLog = calculateWorkLog gitLog
+  submitLogInteractive config workLog
diff --git a/app/Simple.hs b/app/Simple.hs
new file mode 100644
--- /dev/null
+++ b/app/Simple.hs
@@ -0,0 +1,41 @@
+module Simple where
+
+import System.Environment
+import Control.Monad.Except
+import Data.Time
+import Data.Time.Format
+import Data.Either.Utils
+
+import Config
+import Jira
+import Git
+import CLI
+
+
+main :: IO ()
+main = do
+  args <- getArgs
+  config <- forceEither <$> readConfig
+  let workLog = forceEither $ parseArgs args
+  submitLogInteractive config [workLog]
+
+usage = "usage: tempo-simple DATE ISSUE HOURS"
+
+parseArgs :: [String] -> Either String WorkLog
+parseArgs [d,i,h] = do
+  day <- parseDay d
+  hrs <- parseFloat h
+  return $ WorkLog day i hrs
+parseArgs xs
+  | length xs < 3 = throwError $ "not enough arguments; " ++ usage
+  | otherwise     = throwError $ "too many arguments; " ++ usage
+
+parseDay :: String -> Either String Day
+parseDay xs = case parseTimeM False defaultTimeLocale "%Y/%m/%d" xs of
+                Just d  -> return d
+                Nothing -> throwError $ "cannot parse date " ++ xs ++ " in fomrat yyyy/mm/dd"
+
+parseFloat :: String -> Either String Float
+parseFloat xs = case reads xs of
+                  [(n,"")] -> return n
+                  _        -> throwError "cannot parse hours worked"
diff --git a/src/CLI.hs b/src/CLI.hs
new file mode 100644
--- /dev/null
+++ b/src/CLI.hs
@@ -0,0 +1,30 @@
+module CLI
+( submitLogInteractive
+) where
+
+import Control.Monad
+import Text.Printf
+
+import Config
+import Jira
+
+
+askToConfirm :: [WorkLog] -> IO Bool
+askToConfirm workLog = do
+  putStrLn "Will log following items:"
+  mapM_ (putStrLn . sitem) workLog
+  putStrLn "OK? (y/n)"
+  r <- getLine
+  return $ r == "y"
+
+sitem :: WorkLog -> String
+sitem workLog = " * " ++ show workLog
+
+submitLogInteractive :: Config -> [WorkLog] -> IO ()
+submitLogInteractive config workLog = do
+  confirmed <- askToConfirm workLog
+  when confirmed $ do
+    logWork config workLog
+    printf "Work logged. Find your timesheet at https://%s/secure/TempoUserBoard!timesheet.jspa\n" (getJiraHost config)
+  unless confirmed $
+    putStrLn "Abort. Nothing logged."
diff --git a/src/Config.hs b/src/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Config.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module Config
+( Config(..)
+, IssuePattern
+, readConfig
+) where
+
+import System.Directory
+import System.FilePath
+import Data.List.Split
+import Data.ConfigFile
+import Control.Monad.Except
+import Data.ByteString.Char8 (ByteString(..), pack)
+import Data.ByteString.Base64 (decodeLenient)
+
+
+type IssuePattern = String
+
+data Config = Config { getGitRepositories::[FilePath]
+                     , getIssuePatterns::[IssuePattern]
+                     , getJiraHost::String
+                     , getJiraUser::ByteString
+                     , getJiraPassword::ByteString
+                     } deriving (Show)
+
+readConfig :: IO (Either String Config)
+readConfig = do
+  homePath <- getHomeDirectory
+  errorOrConfig <- runExceptT $ do
+    cp       <- join $ liftIO $ readfile emptyCP (homePath </> ".tempo.conf")
+    repos    <- get cp "git" "repos"
+    projects <- get cp "jira" "projects"
+    jiraHost <- get cp "jira" "host"
+    jiraUser <- get cp "jira" "user"
+    jiraPass <- get cp "jira" "pass"
+    return $ Config (splitOn "," repos)
+                    (map projectToPattern (splitOn "," projects))
+                    jiraHost
+                    (pack jiraUser)
+                    (decodeLenient . pack $ jiraPass)
+  return $ case errorOrConfig of
+    (Left err) -> Left $ show err
+    (Right cfg) -> Right cfg
+
+projectToPattern :: String -> IssuePattern
+projectToPattern projectCode = projectCode ++ "\\-[0-9]+"
diff --git a/src/Git.hs b/src/Git.hs
new file mode 100644
--- /dev/null
+++ b/src/Git.hs
@@ -0,0 +1,70 @@
+module Git
+( getGitUser
+, getGitLog
+, calculateWorkLog
+) where
+
+import System.IO
+import System.Process
+import System.FilePath
+
+import Data.Time.Format
+import Text.Regex.Posix
+import Data.Time
+import qualified Data.List as L
+
+import Config
+import Util
+import Jira
+
+
+type User = String
+type GitArgs = [String]
+
+data Commit = Commit Day Issue deriving (Show, Eq, Ord)
+
+
+getGitUser :: IO User
+getGitUser = trim <$> readProcess "git" ["config", "user.email"] []
+
+
+getGitLog :: Config -> User -> GitArgs -> IO [Commit]
+getGitLog config user args = do
+  log <- reflog user args (getGitRepositories config)
+  return $ extractCommits log (getIssuePatterns config)
+
+
+-- extract commits matching any expected issue patter from git log
+extractCommits :: [String] -> [IssuePattern] -> [Commit]
+extractCommits log = concatMap (extractCommits' log)
+
+-- extract commits mathcing expected issue pattern from git log
+extractCommits' :: [String] -> IssuePattern -> [Commit]
+extractCommits' log issuePattern =
+  let relevant = filter (=~ issuePattern) log
+      issues = map (=~ issuePattern) relevant
+      dates = map (parseTimeOrError False defaultTimeLocale "%Y-%m-%d" . take 10) relevant
+  in zipWith Commit dates issues
+
+
+-- extract git log lines for all given repositories, merged to one list
+reflog :: User -> GitArgs -> [FilePath] -> IO [String]
+reflog user gitArgs repos =
+  let listOfLogs = mapM (reflog' user gitArgs) repos
+  in  concat <$> listOfLogs
+
+-- extract git log lines for one repository only
+reflog' :: User -> GitArgs -> FilePath -> IO [String]
+reflog' user gitArgs repoPath = do
+  let args = ["log", "-g", "--all", "--format=%ai %gD %gs", "--author="++user] ++ gitArgs
+      gitProcess = (proc "git" args){cwd = Just repoPath}
+  lines <$> readCreateProcess gitProcess ""
+
+
+calculateWorkLog :: [Commit] -> [WorkLog]
+calculateWorkLog gitLog =
+  let noDuplicates = L.nub gitLog
+      grouped = L.groupBy (\(Commit d1 _) (Commit d2 _) -> d1 == d2) $ L.sort noDuplicates
+      avHours = map (\cs -> 8.0 / (fromIntegral . length $ cs)) grouped
+      logs = zipWith (\cs h -> map (\(Commit d i) -> WorkLog d i h) cs) grouped avHours
+  in  concat logs
diff --git a/src/Jira.hs b/src/Jira.hs
new file mode 100644
--- /dev/null
+++ b/src/Jira.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Jira
+( Issue
+, HoursWorked
+, WorkLog(..)
+, logWork
+) where
+
+import Data.Time
+import Data.Time.Format
+import Text.Printf
+import Network.HTTP.Conduit
+import Control.Monad.Trans.Resource (runResourceT)
+import Data.ByteString.Char8 (ByteString(..), pack)
+
+import Config
+
+
+type Issue = String
+type HoursWorked = Float
+
+data WorkLog = WorkLog Day Issue HoursWorked
+
+instance Show WorkLog where
+  show (WorkLog d i h) = printf "%s - %s - %.1f hours" (show d) i h
+
+
+logWork :: Config -> [WorkLog] -> IO ()
+logWork conf ws = mapM_ (logOne conf) ws
+
+logOne :: Config -> WorkLog -> IO ()
+logOne conf (WorkLog d i h) = do
+  request'' <- parseUrl $ issueUrl conf i
+  let request' = applyBasicAuth (getJiraUser conf) (getJiraPassword conf) request''
+      params = [("time", pack.show $ h), ("user", getJiraUser conf), ("date", datefmt d), ("ansidate", ansidatefmt d)]
+      request = urlEncodedBody params request'
+  manager <- newManager tlsManagerSettings
+  runResourceT $ do
+    response <- http request manager
+    return ()
+
+datefmt :: Day -> ByteString
+datefmt = pack . formatTime defaultTimeLocale "%d/%b/%y"
+
+ansidatefmt :: Day -> ByteString
+ansidatefmt = pack . formatTime defaultTimeLocale "%Y-%m-%d"
+
+issueUrl :: Config -> Issue -> String
+issueUrl conf issue = printf "https://%s/rest/tempo-rest/1.0/worklogs/%s" (getJiraHost conf) issue
diff --git a/src/Util.hs b/src/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Util.hs
@@ -0,0 +1,10 @@
+module Util
+( trim
+) where
+
+import Data.Char (isSpace)
+import Data.ByteString.Char8 (ByteString, pack)
+
+trim :: String -> String
+trim = f . f
+   where f = reverse . dropWhile isSpace
diff --git a/tempo.cabal b/tempo.cabal
new file mode 100644
--- /dev/null
+++ b/tempo.cabal
@@ -0,0 +1,70 @@
+name:                tempo
+version:             0.1.0.0
+synopsis:            Command-line tool to log time-tracking information into JIRA Tempo plugin
+description:         Please see README.md
+homepage:            http://github.com/candidtim/tempo#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Timur Rubeko
+maintainer:          timur@rubeko.com
+copyright:           Timur Rubeko
+category:            NA
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Config
+                     , Util
+                     , Jira
+                     , Git
+                     , CLI
+  build-depends:       base >= 4.7 && < 5
+                     , time
+                     , process
+                     , directory
+                     , filepath
+                     , regex-posix
+                     , split
+                     , ConfigFile
+                     , mtl
+                     , http-conduit
+                     , resourcet
+                     , bytestring
+                     , base64-bytestring
+  default-language:    Haskell2010
+
+executable tempo-git
+  hs-source-dirs:      app
+  main-is:             FromGit.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -main-is Main
+  build-depends:       base
+                     , tempo
+                     , mtl
+                     , MissingH
+  default-language:    Haskell2010
+
+executable tempo-simple
+  hs-source-dirs:      app
+  main-is:             Simple.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -main-is Simple
+  build-depends:       base
+                     , tempo
+                     , time
+                     , mtl
+                     , MissingH
+  default-language:    Haskell2010
+
+test-suite tempo-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base
+                     , tempo
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/candidtim/tempo
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
