diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
 # Changelog
 All notable changes to this project will be documented in this file.
 
+## 0.1.2.0 (released 2020-03-06)
+- FIXED: missing `test-data/` folder in dist tarball prevents tests execution
+- bump _LTS Haskell_ to `15.2`
+
 ## 0.1.1.0 (released 2020-02-26)
 - FIXED: missing `embedded/` folder in dist tarball for _Hackage_ prevents successful build using _Cabal_
 - bump _LTS Haskell_ to `15.1`
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,11 +1,6 @@
-<p align="center"><img src ="https://github.com/vaclavsvejcar/headroom/blob/master/doc/assets/logo.png?raw=true" width="200" /></p>
-
-[![Build Status](https://travis-ci.com/vaclavsvejcar/headroom.svg?branch=master)](https://travis-ci.com/vaclavsvejcar/headroom)
-
 So you are tired of managing license headers in your codebase by hand? Then __Headroom__ is the right tool for you! Now you can define your license header as [Mustache][web:mustache] template, put all the variables (such as author's name, year, etc.) into the [YAML][wiki:yaml] config file and Headroom will take care to add such license headers to all your source code files.
 
 __Table of Contents__
-<!-- TOC -->
 
 - [1. Main Features](#1-main-features)
 - [2. Planned Features](#2-planned-features)
@@ -23,7 +18,6 @@
         - [5.2.1. Supported License Types](#521-supported-license-types)
         - [5.2.2. Supported File Types](#522-supported-file-types)
 
-<!-- /TOC -->
 
 ## 1. Main Features
 - __License Header Management__ - allows to add, replace or drop license headers in source code files.
@@ -31,8 +25,8 @@
 - __Template Generator__ - generates license header templates for most popular _open source_ licenses. You can use these as-is, customize them or ignore them and use your custom templates.
 
 ## 2. Planned Features
-- __init command__ - automates initial Headroom setup for your project (generates config files, detects source code file types and generates license template stubs for them)
-- __binary distribution__ - pre-built binaries will be generated for each release for major OS platforms
+- [[#24]][i24] __Init Command__ - automates initial Headroom setup for your project (generates config files, detects source code file types and generates license template stubs for them)
+- __Binary Distribution__ - pre-built binaries will be generated for each release for major OS platforms
 
 ## 3. Installation
 > Binary distribution, pre-built packages and installation from Stackage will be available soon.
@@ -244,6 +238,7 @@
 | _Scala_      | `scala`   | `.scala`             |
 
 
+[i24]: https://github.com/vaclavsvejcar/headroom/issues/24
 [meta:new-issue]: https://github.com/vaclavsvejcar/headroom/issues/new
 [web:bsd-3]: https://opensource.org/licenses/BSD-3-Clause
 [web:cabal]: https://www.haskell.org/cabal/
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -9,8 +9,10 @@
 
 Functions responsible for application bootstrap.
 -}
+{-# LANGUAGE LambdaCase        #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
+
 module Main where
 
 import           Headroom.Command               ( Command(..)
@@ -38,7 +40,7 @@
     )
 
 bootstrap :: Command -> IO ()
-bootstrap command' = case command' of
+bootstrap = \case
   Run sourcePaths templatePaths variables runMode debug ->
     commandRun (RunOptions runMode sourcePaths templatePaths variables debug)
   c@(Gen _ _) -> do
@@ -46,6 +48,7 @@
     commandGen (GenOptions genMode)
 
 parseGenMode :: MonadThrow m => Command -> m GenMode
-parseGenMode (Gen True  Nothing       ) = return GenConfigFile
-parseGenMode (Gen False (Just license)) = return $ GenLicense license
-parseGenMode _                          = throwM NoGenModeSelected
+parseGenMode = \case
+  Gen True  Nothing        -> pure GenConfigFile
+  Gen False (Just license) -> pure $ GenLicense license
+  _                        -> throwM NoGenModeSelected
diff --git a/headroom.cabal b/headroom.cabal
--- a/headroom.cabal
+++ b/headroom.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.12
 name: headroom
-version: 0.1.1.0
+version: 0.1.2.0
 license: BSD3
 license-file: LICENSE
 copyright: Copyright (c) 2019-2020 Vaclav Svejcar
@@ -48,6 +48,25 @@
     embedded/license/mit/java.mustache
     embedded/license/mit/js.mustache
     embedded/license/mit/scala.mustache
+    test-data/test-template.mustache
+    test-data/code-samples/css/sample1.css
+    test-data/code-samples/css/sample2.css
+    test-data/code-samples/css/sample3.css
+    test-data/code-samples/haskell/full.hs
+    test-data/code-samples/haskell/replaced-simple.hs
+    test-data/code-samples/haskell/stripped.hs
+    test-data/code-samples/html/with-doctype.html
+    test-data/code-samples/html/without-doctype.html
+    test-data/code-samples/java/full.java
+    test-data/code-samples/js/sample1.js
+    test-data/code-samples/js/sample2.js
+    test-data/code-samples/js/sample3.js
+    test-data/code-samples/scala/full.scala
+    test-data/configs/full.yaml
+    test-data/test-traverse/a.html
+    test-data/test-traverse/foo/b.html
+    test-data/test-traverse/foo/test.xml
+    test-data/test-traverse/foo/bar/c.html
 
 source-repository head
     type: git
@@ -93,7 +112,7 @@
         aeson >=1.4.6.0 && <1.5,
         base >=4.7 && <5,
         either >=5.0.1.1 && <5.1,
-        file-embed >=0.0.11.1 && <0.1,
+        file-embed >=0.0.11.2 && <0.1,
         lens >=4.18.1 && <4.19,
         mustache >=2.3.1 && <2.4,
         optparse-applicative >=0.15.1.0 && <0.16,
diff --git a/src/Headroom/AppConfig.hs b/src/Headroom/AppConfig.hs
--- a/src/Headroom/AppConfig.hs
+++ b/src/Headroom/AppConfig.hs
@@ -73,7 +73,7 @@
               -> m AppConfig -- ^ parsed configuration
 loadAppConfig path = do
   appConfig <- liftIO $ B.readFile path >>= parseAppConfig
-  return $ makePathsRelativeTo (takeDirectory path) appConfig
+  pure $ makePathsRelativeTo (takeDirectory path) appConfig
 
 -- | Rewrites all file paths in 'AppConfig' to be relative to given file path.
 makePathsRelativeTo :: FilePath  -- ^ file path to use
@@ -101,7 +101,7 @@
 parseVariables variables = fmap HM.fromList (mapM parse variables)
  where
   parse input = case T.split (== '=') input of
-    [key, value] -> return (key, value)
+    [key, value] -> pure (key, value)
     _            -> throwM $ InvalidVariable input
 
 -- | Validates whether given 'AppConfig' contains valid data.
@@ -109,7 +109,7 @@
                   => AppConfig   -- ^ application config to validate
                   -> m AppConfig -- ^ validated application config (or errors)
 validateAppConfig appConfig = case checked of
-  Success ac'    -> return ac'
+  Success ac'    -> pure ac'
   Failure errors -> throwM $ InvalidAppConfig errors
  where
   checked          = appConfig <$ checkSourcePaths <* checkTemplatePaths
diff --git a/src/Headroom/Command/Gen.hs b/src/Headroom/Command/Gen.hs
--- a/src/Headroom/Command/Gen.hs
+++ b/src/Headroom/Command/Gen.hs
@@ -27,7 +27,7 @@
 
 
 env' :: GenOptions -> LogFunc -> IO Env
-env' opts logFunc = return $ Env { envLogFunc = logFunc, envGenOptions = opts }
+env' opts logFunc = pure $ Env { envLogFunc = logFunc, envGenOptions = opts }
 
 -- | Handler for /Generator/ command.
 commandGen :: GenOptions -- ^ /Generator/ command options
diff --git a/src/Headroom/Command/Run.hs b/src/Headroom/Command/Run.hs
--- a/src/Headroom/Command/Run.hs
+++ b/src/Headroom/Command/Run.hs
@@ -62,8 +62,7 @@
 env' opts logFunc = do
   let startupEnv = StartupEnv { envLogFunc = logFunc, envRunOptions = opts }
   merged <- runRIO startupEnv mergedAppConfig
-  let env = Env { envEnv = startupEnv, envAppConfig = merged }
-  return env
+  pure $ Env { envEnv = startupEnv, envAppConfig = merged }
 
 -- | Handler for /Run/ command.
 commandRun :: RunOptions -- ^ /Run/ command options
@@ -109,13 +108,13 @@
     (\ex -> do
       logDebug $ displayShow (ex :: IOException)
       logWarn $ "Skipping missing configuration file: " <> fromString path
-      return Nothing
+      pure Nothing
     )
   mergeAppConfigs appConfigs = do
     let merged = mconcat appConfigs
     logDebug $ "Source AppConfig instances: " <> displayShow appConfigs
     logDebug $ "Merged AppConfig: " <> displayShow merged
-    return merged
+    pure merged
 
 loadTemplates :: (HasAppConfig env, HasLogFunc env)
               => RIO env (M.Map FileType Text)
@@ -131,7 +130,7 @@
       fmap (t, ) (renderTemplate (acVariables appConfig) (p :: TemplateType))
     )
     parsed
-  return $ M.fromList rendered
+  pure $ M.fromList rendered
  where
   extensions = templateExtensions (Proxy :: Proxy TemplateType)
   findPaths path = findFilesByExts path extensions
@@ -142,7 +141,7 @@
   let fileType = fileTypeByName . T.pack . takeBaseName $ path
   when (isNothing fileType)
        (logWarn $ "Skipping unrecognized template type: " <> fromString path)
-  return fileType
+  pure fileType
 
 findSourceFiles :: HasAppConfig env => [FileType] -> RIO env [FilePath]
 findSourceFiles fileTypes = do
@@ -160,7 +159,7 @@
       withProgress   = fmap (\(i, (h, p)) -> (progress i, h, p)) zipped
       progress curr = Progress curr (L.length paths)
   processed <- mapM (\(i, h, p) -> processHeader i h p) withProgress
-  return (L.length withProgress, L.length . filter (== True) $ processed)
+  pure (L.length withProgress, L.length . filter (== True) $ processed)
  where
   withTemplate (fileType, path) =
     fmap (\t -> (Header fileType t, path)) (M.lookup fileType templates)
@@ -183,7 +182,7 @@
       msg'                   = if skipped then "Skipping file" else msg
   log' $ msg' <> ": " <> fromString path
   writeFileUtf8 path (action header fileContent)
-  return skipped
+  pure skipped
  where
   log' msg = logInfo $ displayShow progress <> "  " <> msg
   chooseAction runMode hasHeader = case runMode of
diff --git a/src/Headroom/Command/Run/Env.hs b/src/Headroom/Command/Run/Env.hs
--- a/src/Headroom/Command/Run/Env.hs
+++ b/src/Headroom/Command/Run/Env.hs
@@ -89,8 +89,8 @@
             -> m AppConfig -- ^ application configuration
 toAppConfig opts = do
   variables' <- parseVariables (roVariables opts)
-  return $ mempty { acSourcePaths   = roSourcePaths opts
-                  , acTemplatePaths = roTemplatePaths opts
-                  , acRunMode       = roRunMode opts
-                  , acVariables     = variables'
-                  }
+  pure $ mempty { acSourcePaths   = roSourcePaths opts
+                , acTemplatePaths = roTemplatePaths opts
+                , acRunMode       = roRunMode opts
+                , acVariables     = variables'
+                }
diff --git a/src/Headroom/FileSystem.hs b/src/Headroom/FileSystem.hs
--- a/src/Headroom/FileSystem.hs
+++ b/src/Headroom/FileSystem.hs
@@ -61,7 +61,7 @@
           -> m [FilePath] -- ^ list of found files
 listFiles fileOrDir = do
   isDir <- doesDirectoryExist fileOrDir
-  if isDir then listDirectory fileOrDir else return [fileOrDir]
+  if isDir then listDirectory fileOrDir else pure [fileOrDir]
  where
   listDirectory dir = do
     names <- getDirectoryContents dir
@@ -69,8 +69,8 @@
     paths <- forM filteredNames $ \name -> do
       let path = dir </> name
       isDirectory <- doesDirectoryExist path
-      if isDirectory then listFiles path else return [path]
-    return $ concat paths
+      if isDirectory then listFiles path else pure [path]
+    pure $ concat paths
 
 -- | Loads file content in UTF8 encoding.
 loadFile :: MonadIO m
diff --git a/src/Headroom/License.hs b/src/Headroom/License.hs
--- a/src/Headroom/License.hs
+++ b/src/Headroom/License.hs
@@ -59,6 +59,6 @@
   | [rawLicenseType, rawFileType] <- TP.splitOn ":" raw = do
     licenseType <- parseLicenseType rawLicenseType
     fileType    <- fileTypeByName rawFileType
-    return $ License licenseType fileType
+    pure $ License licenseType fileType
   | otherwise = Nothing
   where parseLicenseType = readMaybe . T.unpack
diff --git a/src/Headroom/Template/Mustache.hs b/src/Headroom/Template/Mustache.hs
--- a/src/Headroom/Template/Mustache.hs
+++ b/src/Headroom/Template/Mustache.hs
@@ -39,18 +39,18 @@
 parseTemplate' :: MonadThrow m => Maybe Text -> Text -> m Mustache
 parseTemplate' name raw = case MU.compileTemplate templateName raw of
   Left  err -> throwM $ ParseError (T.pack . show $ err)
-  Right res -> return $ Mustache res
+  Right res -> pure $ Mustache res
   where templateName = T.unpack . fromMaybe "" $ name
 
 renderTemplate' :: MonadThrow m => HashMap Text Text -> Mustache -> m Text
 renderTemplate' variables (Mustache t@(MU.Template name _ _)) =
   case MU.checkedSubstitute t variables of
-    ([], rendered) -> return rendered
+    ([], rendered) -> pure rendered
     (errs, rendered) ->
       let errs' = missingVariables errs
       in  if length errs == length errs'
             then throwM $ MissingVariables (T.pack name) errs'
-            else return rendered
+            else pure rendered
  where
   missingVariables = concatMap
     (\case
diff --git a/src/Headroom/Types.hs b/src/Headroom/Types.hs
--- a/src/Headroom/Types.hs
+++ b/src/Headroom/Types.hs
@@ -99,8 +99,8 @@
 
 instance FromJSON RunMode where
   parseJSON (String s) = case T.toLower s of
-    "add"     -> return Add
-    "drop"    -> return Drop
-    "replace" -> return Replace
+    "add"     -> pure Add
+    "drop"    -> pure Drop
+    "replace" -> pure Replace
     _         -> error $ "Unknown run mode: " <> T.unpack s
   parseJSON other = error $ "Invalid value for run mode: " <> show other
diff --git a/test-data/code-samples/css/sample1.css b/test-data/code-samples/css/sample1.css
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/css/sample1.css
@@ -0,0 +1,19 @@
+/*
+ * Copyright AUTHOR
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+body {
+  background: white;
+}
diff --git a/test-data/code-samples/css/sample2.css b/test-data/code-samples/css/sample2.css
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/css/sample2.css
@@ -0,0 +1,6 @@
+
+
+body {
+   background: white;
+ }
+  
diff --git a/test-data/code-samples/css/sample3.css b/test-data/code-samples/css/sample3.css
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/css/sample3.css
@@ -0,0 +1,4 @@
+body {
+    background: white;
+  }
+   
diff --git a/test-data/code-samples/haskell/full.hs b/test-data/code-samples/haskell/full.hs
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/haskell/full.hs
@@ -0,0 +1,20 @@
+
+{-|
+Module      : W
+Description : Short description
+Copyright   : (c) Some Guy, 2013
+                  Someone Else, 2014
+License     : GPL-3
+Maintainer  : sample@email.com
+Stability   : experimental
+Portability : POSIX
+
+Here is a longer description of this module, containing some
+commentary with @some markup@.
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+module Test where
+
+foo :: String
+foo = "Hello, world!"
diff --git a/test-data/code-samples/haskell/replaced-simple.hs b/test-data/code-samples/haskell/replaced-simple.hs
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/haskell/replaced-simple.hs
@@ -0,0 +1,6 @@
+-- This is header
+{-# LANGUAGE OverloadedStrings #-}
+module Test where
+
+foo :: String
+foo = "Hello, world!"
diff --git a/test-data/code-samples/haskell/stripped.hs b/test-data/code-samples/haskell/stripped.hs
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/haskell/stripped.hs
@@ -0,0 +1,5 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Test where
+
+foo :: String
+foo = "Hello, world!"
diff --git a/test-data/code-samples/html/with-doctype.html b/test-data/code-samples/html/with-doctype.html
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/html/with-doctype.html
@@ -0,0 +1,14 @@
+<!--
+    This is some comment.
+    
+-->
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8" />
+        <title>Test title</title>
+    </head>
+    <body>
+        Hello, World!
+    </body>
+</html>
diff --git a/test-data/code-samples/html/without-doctype.html b/test-data/code-samples/html/without-doctype.html
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/html/without-doctype.html
@@ -0,0 +1,14 @@
+<!--
+    This is some comment.
+    
+-->
+
+<html>
+    <head>
+        <meta charset="utf-8" />
+        <title>Test title</title>
+    </head>
+    <body>
+        Hello, World!
+    </body>
+</html>
diff --git a/test-data/code-samples/java/full.java b/test-data/code-samples/java/full.java
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/java/full.java
@@ -0,0 +1,11 @@
+/*
+ * Some existing header here
+ */
+
+package foo;
+
+class Hello {
+    public static void main(String[] args) {
+        System.out.println("Hello, world!");
+    }
+}
diff --git a/test-data/code-samples/js/sample1.js b/test-data/code-samples/js/sample1.js
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/js/sample1.js
@@ -0,0 +1,19 @@
+/*
+ * Copyright AUTHOR
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function answer() {
+  return 42;
+}
diff --git a/test-data/code-samples/js/sample2.js b/test-data/code-samples/js/sample2.js
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/js/sample2.js
@@ -0,0 +1,6 @@
+
+
+function answer() {
+  return 42;
+}
+  
diff --git a/test-data/code-samples/js/sample3.js b/test-data/code-samples/js/sample3.js
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/js/sample3.js
@@ -0,0 +1,3 @@
+function answer() {
+  return 42;
+}
diff --git a/test-data/code-samples/scala/full.scala b/test-data/code-samples/scala/full.scala
new file mode 100644
--- /dev/null
+++ b/test-data/code-samples/scala/full.scala
@@ -0,0 +1,9 @@
+/*
+ * Some existing header here
+ */
+
+package foo
+
+object Hello extends App {
+    println("Hello, world!")
+}
diff --git a/test-data/configs/full.yaml b/test-data/configs/full.yaml
new file mode 100644
--- /dev/null
+++ b/test-data/configs/full.yaml
@@ -0,0 +1,12 @@
+run-mode: add
+
+source-paths:
+  - path/to/src
+
+template-paths:
+  - path/to/dir1
+  - path/to/dir2
+
+variables:
+  copyright: (c) 2019 John Smith
+  email: john.smith@example.com
diff --git a/test-data/test-template.mustache b/test-data/test-template.mustache
new file mode 100644
--- /dev/null
+++ b/test-data/test-template.mustache
@@ -0,0 +1,1 @@
+Hello, {{user}}
diff --git a/test-data/test-traverse/a.html b/test-data/test-traverse/a.html
new file mode 100644
--- /dev/null
+++ b/test-data/test-traverse/a.html
diff --git a/test-data/test-traverse/foo/b.html b/test-data/test-traverse/foo/b.html
new file mode 100644
--- /dev/null
+++ b/test-data/test-traverse/foo/b.html
diff --git a/test-data/test-traverse/foo/bar/c.html b/test-data/test-traverse/foo/bar/c.html
new file mode 100644
--- /dev/null
+++ b/test-data/test-traverse/foo/bar/c.html
diff --git a/test-data/test-traverse/foo/test.xml b/test-data/test-traverse/foo/test.xml
new file mode 100644
--- /dev/null
+++ b/test-data/test-traverse/foo/test.xml
