diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 
 ## Description
 
-Recyle your clipboard selections with greenclip and don't waste your time anymore
+Recycle your clipboard selections with greenclip and don't waste your time anymore
 to reselect things over and over.
 
 **Purpose:**
@@ -16,24 +16,42 @@
 
 **Features:**
   + Integrated with [rofi](https://github.com/DaveDavenport/rofi)
-  + Permanently set some selections to added at the end (set `staticHistoryPath = your/file/with/static/entries` in the config file)
-  + Merge X Primary selection with clipboard selection (set `usePrimarySelectionAsInput = True` in the config file)
+  + Permanently set some selections to added at the end (set `static_history = []` in the config file)
+  + Merge X Primary selection with clipboard selection (set `use_primary_selection_as_input = true` in the config file)
   + Blacklist some applications (see `I want to blacklist some applications !` in the FAQ section)
-  + Copy small images
+  + Copy small images (you can disable it in the config)
 
 ## Installation
 
-1. It's a static binary so drop it anywhere in your $PATH env
+- It's a static binary so drop it anywhere in your $PATH env
 
-```wget https://github.com/erebe/greenclip/releases/download/3.3/greenclip```
+```wget https://github.com/erebe/greenclip/releases/download/v4.2/greenclip```
 
-Alternatively if you are using Archlinux you can install the package from AUR
 
+- Alternatively if you are using Archlinux you can install the package from AUR
+
 ``yay rofi-greenclip``
 
 PS: If you want, you can add a permanent list of selections to be added to your current history. Go see the config file
 
+Configuration file can be found at: 
+```
+❯ cat ~/.config/greenclip.toml
 
+[greenclip]
+  history_file = "/home/erebe/.cache/greenclip.history"
+  max_history_length = 50
+  max_selection_size_bytes = 0
+  trim_space_from_selection = true
+  use_primary_selection_as_input = false
+  blacklisted_applications = []
+  enable_image_support = true
+  image_cache_directory = "/tmp/greenclip"
+  static_history = [
+ '''¯\_(ツ)_/¯''',
+]
+```
+
 ## Usage
 
 Greenclip is intended to be used with [rofi](https://github.com/DaveDavenport/rofi)
@@ -41,7 +59,7 @@
 1. Spawn the daemon ``` greenclip daemon ```
 2. When ever you need to get your selections history ``` rofi -modi "clipboard:greenclip print" -show clipboard -run-command '{cmd}' ```
 3. The entry that you have selected will be in your clipboard now
-4. Configuration file can be found in ```.config/greenclip.cfg```
+4. Configuration file can be found in ```.config/greenclip.toml```
 
 ## Migrating from 2.x version to 3.x one
 
@@ -109,9 +127,9 @@
 
 A. You can also use greenclip with [dmenu](http://tools.suckless.org/dmenu) or [fzf](https://github.com/junegunn/fzf). Example usage:
 
-   `greenclip print | sed '/^$/d' | dmenu -i -l 10 -p clipboard | xargs -r -d'\n' -I '{}' greenclip print '{}'`
+   `greenclip print | grep . | dmenu -i -l 10 -p clipboard | xargs -r -d'\n' -I '{}' greenclip print '{}'`
 
-   `greenclip print | sed '/^$/d' | fzf -e | xargs -r -d'\n' -I '{}' greenclip print '{}'`
+   `greenclip print | grep . | fzf -e | xargs -r -d'\n' -I '{}' greenclip print '{}'`
 
 ----------
 
diff --git a/greenclip.cabal b/greenclip.cabal
--- a/greenclip.cabal
+++ b/greenclip.cabal
@@ -3,7 +3,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           greenclip
-version:        3.4.0
+version:        4.0.0
 synopsis:       Simple clipboard manager to be integrated with rofi
 description:    Simple clipboard manager to be integrated with rofi - Please see README.md
 category:       Linux Desktop
@@ -23,7 +23,7 @@
   main-is: Main.hs
   hs-source-dirs:
       src
-  ghc-options: -Wall -O3
+  ghc-options: -Wall -O3 -Wno-name-shadowing
   build-depends:
       base >= 4 && < 5
     , protolude
@@ -39,9 +39,12 @@
     , unix
     , directory
     , wordexp
+    , tomland
+    , base16-bytestring
+    , cryptohash-md5
     , X11 >= 1.6
   other-modules:
       Clipboard
   default-language: Haskell2010
   default-extensions: Strict
-  pkgconfig-depends: x11, xcb, xau, xdmcp
+  pkgconfig-depends: x11, xcb, xau, xdmcp, xscrnsaver
diff --git a/src/Clipboard.hs b/src/Clipboard.hs
--- a/src/Clipboard.hs
+++ b/src/Clipboard.hs
@@ -16,6 +16,7 @@
 
 import           Data.Binary              (Binary)
 import qualified Data.ByteString          as B
+import qualified Data.Text as T
 import           Lens.Micro
 
 import           System.Directory         (setCurrentDirectory)
@@ -33,6 +34,13 @@
                    | BITMAP ByteString
                    deriving (Show, Eq, Generic, Binary)
 
+selectionLength :: Selection -> Int
+selectionLength (Selection _ (UTF8 a)) = T.length a
+selectionLength (Selection _ (PNG a)) = B.length a
+selectionLength (Selection _ (JPEG a)) = B.length a
+selectionLength (Selection _ (BITMAP a)) = B.length a
+
+
 data Selection = Selection {
     appName   :: Text
   , selection :: SelectionType
@@ -47,7 +55,6 @@
   , mimesPriorities  :: [Atom]
   , defaultMime      :: Atom
 } deriving (Show)
-
 
 test :: IO ()
 test =
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,3 +1,4 @@
+
 {-# LANGUAGE DuplicateRecordFields #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
@@ -13,37 +14,59 @@
 import           Protolude.Conv        (toS)
 
 import           Control.Monad.Catch   (MonadCatch, catchAll)
+import qualified Crypto.Hash.MD5       as H
 import           Data.Binary           (decodeFile, encode)
 import qualified Data.ByteString       as B
+import qualified Data.ByteString.Base16 as BB
+import qualified Data.ByteString.Char8 as BC
 import           Data.List             (dropWhileEnd)
 import qualified Data.Text             as T
+import qualified Data.Text.Encoding    as TE
 import           Data.Vector           (Vector)
 import qualified Data.Vector           as V
 import           Lens.Micro
-import           Lens.Micro.Mtl
+import           Lens.Micro.Mtl    hiding ((.=))
 import qualified System.Directory      as Dir
 import           System.Posix.Files    (setFileMode)
 import           System.Environment    (lookupEnv)
 import           System.IO             (hClose, hGetContents)
 import           System.Timeout        (timeout)
 import           System.Wordexp.Simple (wordexp)
+--import           System.Posix.Temp     (mkdtemp)
 
+import Toml (TomlCodec, (.=))
+import qualified Toml
+
 import qualified Clipboard             as Clip
 
 
-data Command = DAEMON | PRINT | COPY Text | CLEAR | HELP deriving (Show, Read)
+data Command = DAEMON | PRINT | COPY Text | CLEAR | PRUNE FilePath | HELP deriving (Show, Read)
 
 data Config = Config
   { maxHistoryLength           :: Int
+  , maxItemSizeBytes           :: Int
   , historyPath                :: Text
-  , staticHistoryPath          :: Text
   , imageCachePath             :: Text
   , usePrimarySelectionAsInput :: Bool
   , blacklistedApps            :: [Text]
   , trimSpaceFromSelection     :: Bool
   , enableImageSupport         :: Bool
+  , staticHistory              :: [Text]
   } deriving (Show, Read)
 
+configCodec :: TomlCodec Config
+configCodec = Config
+    <$> Toml.int "max_history_length"  .= maxHistoryLength
+    <*> Toml.int "max_selection_size_bytes" .= maxItemSizeBytes
+    <*> Toml.text "history_file" .= historyPath
+    <*> Toml.text "image_cache_directory" .= imageCachePath
+    <*> Toml.bool "use_primary_selection_as_input" .= usePrimarySelectionAsInput
+    <*> Toml.arrayOf Toml._Text  "blacklisted_applications" .= blacklistedApps
+    <*> Toml.bool "trim_space_from_selection" .= trimSpaceFromSelection
+    <*> Toml.bool "enable_image_support" .= enableImageSupport
+    <*> Toml.arrayOf Toml._Text  "static_history" .= staticHistory
+
+
 type ClipHistory = Vector Clip.Selection
 
 readFile :: FilePath -> IO ByteString
@@ -60,13 +83,11 @@
 
 getStaticHistory :: (MonadIO m, MonadReader Config m) => m ClipHistory
 getStaticHistory = do
-  storePath <- view $ to (toS . staticHistoryPath)
-  liftIO $ readH storePath `catchAll` const mempty
-  where
-    readH filePath = readFile filePath <&> V.fromList . fmap toSelection . T.lines . toS
-    toSelection txt = Clip.Selection "greenclip" (Clip.UTF8 txt)
+  history <- view $ to (staticHistory)
+  return . V.fromList $ Clip.Selection "greenclip" . Clip.UTF8 <$> history
 
 
+
 storeHistory :: (MonadIO m, MonadReader Config m) => ClipHistory -> m ()
 storeHistory history = do
   storePath <- view $ to (toS . historyPath)
@@ -75,6 +96,17 @@
     writeH storePath = B.writeFile storePath . toS . encode . V.toList
 
 
+pruneHistory :: (MonadIO m, MonadReader Config m) => FilePath -> m ()
+pruneHistory path = do
+  targets <- liftIO $ BC.lines <$> readFile path
+  history <- getHistory
+  storeHistory $ V.filter (go targets) history
+  where
+    go ts (Clip.Selection _ (Clip.UTF8 x)) = hashText x `notElem` ts
+    go _  _                                = False
+    hashText = BB.encode . H.hash . TE.encodeUtf8
+
+
 appendToHistory :: (MonadIO m, MonadReader Config m) => Clip.Selection -> ClipHistory -> m (ClipHistory, ClipHistory)
 appendToHistory sel history' = do
   trimSelection <- view $ to trimSpaceFromSelection
@@ -151,8 +183,16 @@
     innerloop :: (MonadIO m, MonadReader Config m) => [(IO (Maybe Clip.Selection), Maybe Clip.Selection)] -> ClipHistory -> m ClipHistory
     innerloop getSelections history = do
       -- Get selection from enabled clipboards
-      (getSelections', sel) <- liftIO $ getSelection getSelections
+      (getSelections', rawSelection) <- liftIO $ getSelection getSelections
 
+      -- Do not store selection items above threshold size
+      maxItemSize <- view (to maxItemSizeBytes)
+      let sel = case rawSelection of
+            Nothing -> Nothing
+            Just selection -> if maxItemSize > 0 && Clip.selectionLength selection >= maxItemSize
+                              then Nothing
+                              else Just selection
+             
       -- Do not use selection coming from blacklisted app
       liftIO $ when (isJust sel) (print (Clip.appName <$> sel))
       blacklist <- view (to blacklistedApps)
@@ -224,40 +264,47 @@
 getConfig :: IO Config
 getConfig = do
   home <- Dir.getHomeDirectory
-  let cfgPath = home <> "/.config/greenclip.cfg"
-
-  cfgStr <- readFile cfgPath `catchAll` const mempty
-
-  let unprettyCfg' = cfgStr & T.strip . T.replace "\n" "" . toS
-  let unprettyCfg = if "trimSpaceFromSelection" `T.isInfixOf` unprettyCfg'
-                      then unprettyCfg'
-                      else T.replace "}" ", trimSpaceFromSelection = True }" unprettyCfg'
-  let cfgMaybe = readMaybe $ toS unprettyCfg
-  let cfg = fromMaybe defaultConfig cfgMaybe
-
-  -- Write back the config file if the current one was invalid
-  _ <- if isNothing cfgMaybe || unprettyCfg /= unprettyCfg'
-        then let prettyCfg = show cfg & T.replace "," ",\n" . T.replace "{" "{\n " . T.replace "}" "\n}"
-             in writeFile cfgPath prettyCfg
-        else return ()
-
-  historyPath' <- expandHomeDir $ cfg ^. to historyPath
-  staticHistoryPath' <- expandHomeDir $ cfg ^. to staticHistoryPath
-  imageCachePath' <- expandHomeDir $ cfg ^. to imageCachePath
-
-  return $ cfg { historyPath = historyPath'
-               , staticHistoryPath = staticHistoryPath'
-               , imageCachePath = imageCachePath'
-               }
+  let configPath = home <> "/.config/greenclip.toml"
+  
+  configExist <- Dir.doesFileExist configPath
+  when (not configExist) $ do 
+    config <- Toml.encode (Toml.table configCodec "greenclip") <$> defaultConfig
+    writeFile configPath config
+    return ()
+  
+  tomlRes <- Toml.decodeFileEither (Toml.table configCodec "greenclip") configPath
+  when (isLeft tomlRes) $ do
+    die . toS $  "Error parsing the config file at " <> (show configPath) <> "\n" <> Toml.prettyTomlDecodeErrors (fromLeft mempty tomlRes)
+  
+  let cfg = fromRight (Config 50 0 "" "" False [] True True []) tomlRes 
+  
+  -- Replace $HOME|~|*... in config path
+  cfg <- do
+    imgCachePath <- wordexp . toS $ imageCachePath cfg
+    historyP <- wordexp . toS $ historyPath cfg 
+    return $ cfg { imageCachePath = (toS $ headDef "" imgCachePath), historyPath = (toS $ headDef "" historyP)}
+    
+  -- if it ends with / we don't create a temp directory
+  -- user is responsible for it
+  -- cfg <- if (lastDef ' ' (toS $ imageCachePath cfg) /= '/')
+  --    then do
+  --      dirPath <- mkdtemp $ (toS $ imageCachePath cfg)
+  --      return $ cfg { imageCachePath = toS dirPath }
+  --    else return cfg
+     
+  return cfg
 
   where
-    defaultConfig = Config 50 "~/.cache/greenclip.history" "~/.cache/greenclip.staticHistory" "/tmp/greenclip/" False [] True True
-    expandHomeDir str = (toS . fromMaybe (toS str) . listToMaybe <$> wordexp (toS str)) `catchAll` (\_ -> return $ toS str)
+    defaultConfig = do 
+      homeDir <- toS . fromMaybe mempty . listToMaybe <$> wordexp "~/"
+      return $ Config 50 0 (homeDir <> ".cache/greenclip.history") "/tmp/greenclip" False [] True True 
+        ["Greenclip has been updated to v4.1, update your new config file at ~/.config/greenclip.toml"]
 
 
 parseArgs :: [Text] -> Command
 parseArgs ("daemon":_)   = DAEMON
 parseArgs ["clear"]      = CLEAR
+parseArgs ["prune", p]   = PRUNE $ T.unpack p
 parseArgs ["print"]      = PRINT
 parseArgs ["print", sel] = COPY sel
 parseArgs _              = HELP
@@ -269,13 +316,15 @@
     DAEMON   -> runReaderT runDaemon cfg
     PRINT    -> runReaderT printHistoryForRofi cfg
     CLEAR    -> runReaderT (storeHistory mempty) cfg
+    PRUNE p  -> runReaderT (pruneHistory p) cfg
     -- Should rename COPY into ADVERTISE but as greenclip is already used I don't want to break configs
     -- of other people
     COPY sel -> runReaderT (advertiseSelection sel) cfg
-    HELP     -> putText $ "greenclip v3.3 -- Recyle your clipboard selections\n\n" <>
+    HELP     -> putText $ "greenclip v4.2 -- Recyle your clipboard selections\n\n" <>
                           "Available commands\n" <>
                           "daemon: Spawn the daemon that will listen to selections\n" <>
                           "print:  Display all selections history\n" <>
+                          "prune FILE: Remove selections in list of md5 hashes in FILE\n" <>
                           "clear:  Clear history\n" <>
                           "help:   Display this message\n"
 
