diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Command Line Interface File Manager
 Clifm is a small file manager written in Haskell with a terminal-based interface. It allows you to explore directories in multiple Panes/Tabs and perform basic operations.
 
-![screenshot](screenshot.png)
+![screenshot](https://github.com/pasqu4le/clifm/raw/master/screenshot.png)
 
 > Note: this is still an experiment. Directory navigation will do no harm, but double-check before starting operations on your file system. I take no responsibility for what you do with this software.
 
diff --git a/clifm.cabal b/clifm.cabal
--- a/clifm.cabal
+++ b/clifm.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.5.0.0
+version:             0.5.2.1
 
 -- A short (one-line) description of the package.
 synopsis:            Command Line Interface File Manager
diff --git a/src/Widgets/Menu.hs b/src/Widgets/Menu.hs
--- a/src/Widgets/Menu.hs
+++ b/src/Widgets/Menu.hs
@@ -27,8 +27,8 @@
 menuType :: Lens' Menu MenuType
 menuType = lens _menuType (\menu x -> menu {_menuType = x})
 
-fromEntry :: Lens' Clipboard Entry.Entry
-fromEntry = lens _fromEntry (\board x -> board {_fromEntry = x})
+fromEntry :: Traversal' Clipboard Entry.Entry
+fromEntry = filtered (not . isEmpty) . lens _fromEntry (\board x -> board {_fromEntry = x})
 
 -- creation
 make :: Menu
@@ -77,7 +77,7 @@
   | Tab.isDir tab = dirTabButtons ++ entryTabButtons orderType ++ anyTabButtons
   | Tab.isSearch tab = entryTabButtons orderType ++ anyTabButtons
   | otherwise = anyTabButtons
-  where orderType = view Tab.orderType tab
+  where (Just orderType) = preview Tab.orderType tab
 
 dirTabButtons :: [(Widget Name, Maybe String, Name)]
 dirTabButtons = [
diff --git a/src/Widgets/Pane.hs b/src/Widgets/Pane.hs
--- a/src/Widgets/Pane.hs
+++ b/src/Widgets/Pane.hs
@@ -29,9 +29,8 @@
 currentTab :: Lens' Pane Tab.Tab
 currentTab = tabZipper.focus
 
---NOTE: needs to filter empty tabs, or it will fail
 entries :: Traversal' Pane Entry.Entry
-entries = tabZipper.traverse.filtered (not . Tab.isEmpty).Tab.entries
+entries = tabZipper.traverse.Tab.entries
 
 -- creation
 empty :: PaneName -> Pane
diff --git a/src/Widgets/Prompt.hs b/src/Widgets/Prompt.hs
--- a/src/Widgets/Prompt.hs
+++ b/src/Widgets/Prompt.hs
@@ -8,6 +8,7 @@
 import Data.Monoid ((<>))
 import Data.Functor (($>))
 import Control.Monad(when,forM_)
+import Data.Maybe (fromJust)
 import Control.Monad.IO.Class (liftIO)
 import Control.Concurrent (forkFinally, ThreadId, killThread)
 import Control.Exception (try, throw, displayException, SomeException, fromException)
@@ -21,9 +22,10 @@
 import Brick.BChan (BChan, writeBChan)
 import Graphics.Vty (Event(EvKey), Key(..))
 import Data.Time.Format (formatTime, defaultTimeLocale)
-import System.FilePath (isValid, takeDirectory, (</>), takeFileName)
+import Conduit
+import System.FilePath (isValid, takeDirectory, (</>), takeFileName, makeRelative)
 import System.Directory (doesFileExist, doesDirectoryExist, createDirectory, renameFile,
-  copyFileWithMetadata, removeFile, removeDirectoryRecursive, getDirectoryContents,
+  copyFileWithMetadata, removeFile, removeDirectoryRecursive, createDirectoryIfMissing,
   readable, writable, executable, searchable)
 
 data Prompt = Prompt {_originTab :: Tab.Tab, _originPane :: PaneName, _action :: Action} deriving Show
@@ -69,8 +71,8 @@
     | Menu.isEmpty clip = DisplayError "The clipboard is empty"
     | Tab.isEmpty tab = DisplayError "You cannot paste into an empty tab"
     | Tab.isSearch tab = DisplayError "You cannot paste into a search tab"
-    | Menu.isCopy clip = Copy (clip ^. Menu.fromEntry) (tab ^. Tab.path)
-    | Menu.isCut clip = Cut (clip ^. Menu.fromEntry) (tab ^. Tab.path)
+    | Menu.isCopy clip = Copy (fromJust $ preview Menu.fromEntry clip) (tab ^. Tab.path)
+    | Menu.isCut clip = Cut (fromJust $ preview Menu.fromEntry clip) (tab ^. Tab.path)
     | otherwise = DisplayError "Cannot paste: unknown error"
   in Prompt tab pName checked
 
@@ -309,31 +311,18 @@
 
 -- files functions not covered by System.Directory nor System.FilePath
 moveFileWithMetadata :: FilePath -> FilePath -> IO ()
-moveFileWithMetadata o d = do
-  copyFileWithMetadata o d
-  removeFile o
+moveFileWithMetadata src dst = do
+  copyFileWithMetadata src dst
+  removeFile src
 
 moveDirectoryRecursive :: FilePath -> FilePath -> IO ()
-moveDirectoryRecursive o d = do
-  copyDirectoryRecursive o d
-  removeDirectoryRecursive o
+moveDirectoryRecursive src dst = do
+  copyDirectoryRecursive src dst
+  removeDirectoryRecursive src
 
--- taken from https://stackoverflow.com/questions/6807025/what-is-the-haskell-way-to-copy-a-directory
 copyDirectoryRecursive ::  FilePath -> FilePath -> IO ()
-copyDirectoryRecursive src dst = do
-  whenM (not <$> doesDirectoryExist src) $ throw (userError "source does not exist")
-  whenM (doesFileOrDirectoryExist dst) $ throw (userError "destination already exists")
-  createDirectory dst
-  content <- getDirectoryContents src
-  let xs = filter (`notElem` [".", ".."]) content
-  forM_ xs $ \name -> do
-    let srcPath = src </> name
-    let dstPath = dst </> name
-    isDirectory <- doesDirectoryExist srcPath
-    if isDirectory
-      then copyDirectoryRecursive srcPath dstPath
-      else copyFileWithMetadata srcPath dstPath
-  where
-    doesFileOrDirectoryExist x = orM [doesDirectoryExist x, doesFileExist x]
-    orM xs = or <$> sequence xs
-    whenM s r = s >>= flip when r
+copyDirectoryRecursive src dst = runConduitRes
+  $ sourceDirectoryDeep False src
+  .| mapC (\fPath -> (fPath, dst </> (makeRelative src fPath)))
+  .| iterMC (liftIO . createDirectoryIfMissing True . takeDirectory . snd)
+  .| mapM_C (\(srcFile, dstFile)  -> liftIO $ copyFileWithMetadata srcFile dstFile)
diff --git a/src/Widgets/Tab.hs b/src/Widgets/Tab.hs
--- a/src/Widgets/Tab.hs
+++ b/src/Widgets/Tab.hs
@@ -5,9 +5,10 @@
 import Control.Lens hiding (Empty)
 import Data.List (sortOn, isInfixOf, elemIndex)
 import Data.Char (toLower)
-import Data.Maybe (fromMaybe)
+import Data.Maybe (fromMaybe, fromJust)
 import Data.Time.Clock (UTCTime(..), secondsToDiffTime)
 import Data.Time.Calendar (Day(ModifiedJulianDay))
+import Conduit
 import System.FilePath (takeFileName, takeDirectory, (</>))
 import System.Directory (doesDirectoryExist, doesFileExist, listDirectory)
 import Brick.Types (Widget, EventM)
@@ -41,25 +42,25 @@
   show ModificationTime = "modified"
 
 -- lenses
-name :: Lens' Tab String
-name = lens _name (\tab n -> tab {_name = n})
+name :: Traversal' Tab String
+name = unlessEmpty . lens _name (\tab n -> tab {_name = n})
 
-path :: Lens' Tab FilePath
-path = lens _path (\tab n -> tab {_path = n})
+path :: Traversal' Tab FilePath
+path = unlessEmpty . lens _path (\tab n -> tab {_path = n})
 
-entryList :: Lens' Tab (List Name Entry.Entry)
-entryList = lens _entryList (\tab n -> tab {_entryList = n})
+entryList :: Traversal' Tab (List Name Entry.Entry)
+entryList = unlessEmpty . lens _entryList (\tab n -> tab {_entryList = n})
 
-entryOrder :: Lens' Tab EntryOrder
-entryOrder = lens _entryOrder (\tab n -> tab {_entryOrder = n})
+entryOrder :: Traversal' Tab EntryOrder
+entryOrder = unlessEmpty . lens _entryOrder (\tab n -> tab {_entryOrder = n})
 
-query :: Lens' Tab String
-query = lens _query (\tab n -> tab {_query = n})
+query :: Traversal' Tab String
+query = onSearch . lens _query (\tab n -> tab {_query = n})
 
-orderType :: Lens' Tab OrderType
+orderType :: Traversal' Tab OrderType
 orderType = entryOrder.entryOrderType
 
-orderInverted :: Lens' Tab Bool
+orderInverted :: Traversal' Tab Bool
 orderInverted = entryOrder.entryOrderInverted
 
 entryOrderType :: Lens' EntryOrder OrderType
@@ -68,7 +69,12 @@
 entryOrderInverted :: Lens' EntryOrder Bool
 entryOrderInverted = lens _inverted (\tab n -> tab {_inverted = n})
 
---NOTE: remember that it will fail for Empty tabs
+onSearch :: Traversal' Tab Tab
+onSearch = filtered isSearch
+
+unlessEmpty :: Traversal' Tab Tab
+unlessEmpty = filtered (not . isEmpty)
+
 entries :: Traversal' Tab Entry.Entry
 entries = entryList.traverse
 
@@ -132,9 +138,7 @@
   ]
 
 renderEntryOrder :: Tab -> Widget Name
-renderEntryOrder tab = str $ case tab of
-  Empty -> ""
-  _ -> " by " ++ views entryOrder show tab
+renderEntryOrder = str . maybe "" (" by " ++) . previews entryOrder show
 
 renderPath :: Tab -> Widget Name
 renderPath tab = str $ case tab of
@@ -143,7 +147,10 @@
   Search {_path = p, _query = q} -> " search for " ++ q ++ " in " ++ takeFileName p
 
 renderContent :: Bool -> Tab -> Widget Name
-renderContent _ Empty = vBox (lns ++ [fill ' '])
+renderContent hasFoc = maybe emptyContent (renderList Entry.render hasFoc) . preview entryList
+
+emptyContent :: Widget Name
+emptyContent = vBox (lns ++ [fill ' '])
   where lns = map strWrap $ lines "Command Line Interface File Manager\n \n\
     \clifm allows you to explore directories on multiple tabs.\nIf your terminal\
     \ has mouse support you can click on some elements to interact with them, \
@@ -154,33 +161,29 @@
     \BackTab key or use Ctrl + Left or Right arrow key to swap them.\n \nYou can \
     \see every other possible action as a button in the bottom, or you can use \
     \them as Keys combination.\n \nTo see them all please refer to the README"
-renderContent hasFocus tab = views entryList (renderList Entry.render hasFocus) tab
 
 -- event handling and state-changing
 handleEvent :: Event -> Tab -> EventM Name Tab
-handleEvent _ Empty = return Empty
-handleEvent event tab = case event of
-  EvKey (KChar 'o') [] -> return $ changeOrder tab
-  EvKey (KChar 'i') [] -> return $ invertOrder tab
-  _ -> entryList (handleListEvent event) tab
+handleEvent event = case event of
+  EvKey (KChar 'o') [] -> return . changeOrder
+  EvKey (KChar 'i') [] -> return . invertOrder
+  _ -> entryList (handleListEvent event)
 
 changeOrder :: Tab -> Tab
-changeOrder Empty = Empty
 changeOrder tab = tab
   & entryOrder .~ newOrder
   & entryList.listElementsL._tail .~ sorted
   & entryList.listSelectedL ?~ maybe 0 (+1) ((`Vect.elemIndex` sorted) =<< selectedEntry tab)
   where
-    newOrder = over entryOrderType nextOrderType $ view entryOrder tab
+    newOrder = over entryOrderType nextOrderType . fromJust $ preview entryOrder tab
     sorted = Vect.fromList . sortEntries newOrder . toList $ view (entryList.listElementsL._tail) tab
 
 invertOrder :: Tab -> Tab
-invertOrder Empty = Empty
-invertOrder tab = tab 
+invertOrder tab = tab
   & orderInverted %~ not 
   & entryList.listElementsL._tail %~ Vect.reverse
   & entryList.listSelectedL %~ fmap (\idx -> if idx == 0 then 0 else size - idx)
-  where size = views (entryList.listElementsL) Vect.length tab
+  where size = fromJust $ previews (entryList.listElementsL) Vect.length tab
 
 reload :: PaneName -> Tab -> IO Tab
 reload pName tab = case tab of
@@ -195,8 +198,7 @@
   where newElems = listElements newList
 
 moveToRow :: Int -> Tab -> Tab
-moveToRow _ Empty = Empty
-moveToRow row tab = tab & entryList %~ listMoveTo row
+moveToRow row = over entryList (listMoveTo row)
 
 -- utility
 isDir :: Tab -> Bool
@@ -213,7 +215,7 @@
 
 selectedEntry :: Tab -> Maybe Entry.Entry
 selectedEntry Empty = Nothing
-selectedEntry tab = snd <$> listSelectedElement (view entryList tab)
+selectedEntry tab = snd <$> listSelectedElement (fromJust $ preview entryList tab)
 
 nextOrderType :: OrderType -> OrderType
 nextOrderType order
@@ -235,19 +237,7 @@
 zeroTime = UTCTime (ModifiedJulianDay 0) (secondsToDiffTime 0)
 
 searchRecursive :: FilePath -> String -> IO [FilePath]
-searchRecursive filePath searchQuery = do
-  subNames <- listDirectory filePath
-  filePaths <- listRecursive $ map (filePath </>) subNames
-  return $ filter (isInfixOf searchQuery . takeFileName) filePaths
-
-listRecursive :: [FilePath] -> IO [FilePath]
-listRecursive [] = return []
-listRecursive (filePath:filePaths) = do
-  isDir <- doesDirectoryExist filePath
-  isFile <- doesFileExist filePath
-  if isFile then (filePath :) <$> listRecursive filePaths
-  else if isDir then do
-    subNames <- listDirectory filePath
-    let subPaths = map (filePath </>) subNames
-    (filePath :) <$> listRecursive (subPaths ++ filePaths)
-  else listRecursive filePaths
+searchRecursive filePath searchQuery = runConduitRes
+  $ sourceDirectoryDeep False filePath
+  .| filterC (isInfixOf searchQuery . takeFileName)
+  .| sinkList
