diff --git a/handsy.cabal b/handsy.cabal
--- a/handsy.cabal
+++ b/handsy.cabal
@@ -1,7 +1,18 @@
 name:          handsy
-version:       0.0.10
+version:       0.0.11
 synopsis:      A DSL to describe common shell operations and interpeters for running them locally and remotely.
--- description:   
+description:
+    @handsy@ is a small library mainly for applications which should make some
+    operations on remote machines by SSH. It currently provides you:
+    .
+    * A DSL describing basic system operations('command', 'readFile', 'writeFile' etc.)
+    * Two interpreters for running this DSL locally or via SSH('run' and 'runRemote')
+    * Some utility functions for common commands('os', 'mkTemp' etc.)
+    .
+    If you're looking for a shell scripting alternative, look at @turtle@, @shelly@ or
+    @shellmate@ packages. @handsy@ is mostly relevant for the ability to apply simple
+    commands remotely.
+
 Homepage:      https://github.com/utdemir/handsy
 license:       BSD3
 author:        Utku Demir
@@ -19,6 +30,7 @@
                     System.Handsy.Remote
                     System.Handsy.Util
                     System.Handsy.Internal
+                    System.Handsy.Tutorial
   build-depends:    base >=4.6 && <4.8
                   , bytestring
                   , process
@@ -28,19 +40,21 @@
                   , shell-escape
                   , retry
                   , data-default-class
+                  , split
   hs-source-dirs:   src
   default-language: Haskell2010
 
   ghc-options: -Wall
-  ghc-options: -Wall
+
 test-suite tests
-    type:             exitcode-stdio-1.0
-    main-is:          Test.hs
-    default-language: Haskell2010
-    hs-source-dirs:   test
-    build-depends: base >=4.6 && < 4.8
-                 , handsy
-                 , bytestring
-                 , tasty
-                 , tasty-hunit
-                 , tasty-th
+  type:             exitcode-stdio-1.0
+  main-is:          Test.hs
+  default-language: Haskell2010
+  hs-source-dirs:   test
+  build-depends:    base >=4.6 && < 4.8
+                  , handsy
+                  , bytestring
+                  , tasty
+                  , tasty-hunit
+                  , tasty-th
+  ghc-options: -Wall
diff --git a/src/System/Handsy/Tutorial.hs b/src/System/Handsy/Tutorial.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Handsy/Tutorial.hs
@@ -0,0 +1,84 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+module System.Handsy.Tutorial (
+    -- * Introduction
+    -- $introduction
+
+    -- * Examples
+    -- $examples
+    ) where
+
+import           System.Handsy
+import           System.Handsy.Remote
+import           System.Handsy.Util
+
+{- $introduction
+    @handsy@ is a small library mainly for applications which should make some
+    operations on remote machines by SSH. It currently provides you:
+
+    * A DSL describing basic system operations('command', 'readFile', 'writeFile' etc.)
+    * Two interpreters for running this DSL locally or via SSH('run' and 'runRemote')
+    * Some utility functions for common commands('os', 'mkTemp' etc.)
+
+    If you're looking for a shell scripting alternative, look at @turtle@, @shelly@ or
+    @shellmate@ packages. @handsy@ is mostly relevant for the ability to apply simple
+    commands remotely.
+-}
+
+{- $examples
+    Here is a simple demonstration:
+
+@
+import           Control.Applicative    ((\<$>))
+import           Control.Monad.IO.Class (liftIO)
+import qualified Data.ByteString.Lazy   as B
+
+import qualified System.Handsy          as H
+import qualified System.Handsy.Remote   as H
+import qualified System.Handsy.Util     as H
+
+demo :: H.Handsy B.ByteString
+demo = do
+  os <- H.os
+
+  -- We can do IO in Handsy monad
+  liftIO . putStrLn $ "Hello from " ++ maybe \"UnknownOS\" show os ++ "!"
+
+  tmpFile <- H.mkTemp "handsy"
+  H.writeFile tmpFile "hello world!"
+  H.stdout \<$\> H.command "cat" [tmpFile] H.def
+@
+
+    And now we can run it:
+
+@
+  runHere  = 'H.run' H.def demo >>= print
+  runThere = 'H.runRemote' H.def "root@google.com" H.def{H.sshPort=2222} demo >>= print
+@
+
+> λ> runHere
+> Hello from NixOS!
+> "hello world!"
+> λ> runThere
+> Hello from CentOS!
+> "hello world!"
+
+    Internally, Handsy converts the DSL terms into series of shell commands and
+    'run' and 'runRemote' functions describes how to apply those shell
+    commands.
+
+    You can see the given shell commands using 'debug' option:
+
+> λ> H.run H.def{debug=True} demo >>= print
+> cat /etc/os-release
+> Hello from NixOS!
+> mktemp $'--suffix=handsy'
+> dd $'of=/run/user/1002/tmp.N3TlYC9Jfwhandsy'
+> cat /run/user/1002/tmp.N3TlYC9Jfwhandsy
+> "hello world!"
+
+
+
+-}
+
+
diff --git a/src/System/Handsy/Util.hs b/src/System/Handsy/Util.hs
--- a/src/System/Handsy/Util.hs
+++ b/src/System/Handsy/Util.hs
@@ -9,10 +9,13 @@
 import           Control.Monad.IO.Class
 import           Data.Bool
 import qualified Data.ByteString.Lazy.Char8 as C
+import           Data.List.Split
 import           Prelude                    hiding (appendFile, readFile,
                                              writeFile)
 import           System.Handsy
 
+-- * Helpers for parsing return values of 'command' and 'shell'
+
 class IsReturnValue a where
   stdout   :: a -> C.ByteString
   stderr   :: a -> C.ByteString
@@ -36,14 +39,16 @@
   ExitSuccess   -> True
   ExitFailure _ -> False
 
--- | Waits specified number of seconds
-sleep :: Int -> Handsy ()
-sleep = liftIO . threadDelay . (* 1000000)
-
 -- | Extract lines from a ByteString. Useful for parsing unix commands.
 strLines :: C.ByteString -> [String]
 strLines = lines . C.unpack
 
+-- * Frequently used functionality
+
+-- | Waits specified number of seconds
+sleep :: Int -> Handsy ()
+sleep = liftIO . threadDelay . (* 1000000)
+
 -- | Creates a temporary file
 mkTemp :: String -> Handsy String
 mkTemp suffix = head . strLines . fst
@@ -57,3 +62,21 @@
 -- | Returns if the specified process is running. Uses `pidof`
 isRunning :: String -> Handsy Bool
 isRunning p = isSuccessful <$> command "pidof" ["-s", "-x", p] def
+
+data OS = NixOS | Debian | Ubuntu | RHEL | CentOS | Fedora | ArchLinux
+  deriving (Show, Eq)
+
+{-| Guesses the os using `/etc/os-release`. This currently only supports Linux distributions
+    abiding systemd standards. -}
+os :: Handsy (Maybe OS)
+os = parseOsRelease <$> readFile "/etc/os-release" >>= return . \case
+    Just "ubuntu" -> Just Ubuntu
+    Just "debian" -> Just Debian
+    Just "nixos"  -> Just NixOS
+    Just "rhel"   -> Just RHEL
+    Just "centos" -> Just CentOS
+    Just "fedora" -> Just Fedora
+    Just "arch"   -> Just ArchLinux
+    _             -> Nothing
+  where parseOsRelease = fmap (filter $ not . flip elem "'\"") -- Hack to unquote
+          <$> lookup "ID" . map ((\(x:xs) -> (x, concat xs)) . splitOn "=") . strLines
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell   #-}
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
 
 module Main where
 
@@ -14,10 +15,7 @@
 import qualified Data.ByteString.Lazy       as B
 import qualified Data.ByteString.Lazy.Char8 as C
 import           Data.Char
-import           Data.List
-import           System.Exit
 
-import           Test.Tasty
 import           Test.Tasty.HUnit
 import           Test.Tasty.TH
 
