diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Revision history for execpath
 
+## 0.1.1.0 -- 2019-01-22
+
+* Generate an IO action to check for missing dependencies at runtime.
+
+* Add ability to use TH to load a list of specific executables.
+
 ## 0.1.0.1 -- 2019-01-22
 
 * Force output of lazy read functions to normal form to prevent
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,12 +1,16 @@
 # Shh
 
+[![Hackage](https://img.shields.io/hackage/v/shh.svg?colorB=%23999)](http://hackage.haskell.org/package/shh)
+[![Build Status](https://travis-ci.org/luke-clifton/shh.svg?branch=master)](https://travis-ci.org/luke-clifton/shh)
+
 Shh is a library to enable convinient shell-like programming in Haskell.
 It works well in scripts, and from GHCi, allowing you to use GHCi as a shell.
 
 It supports
 
  * Automatically defining a function for each executable on your `$PATH`
-   using template Haskell.
+   using template Haskell, as well as a runtime check to ensure they all
+   exist on startup.
 
  * Redirction of stdout and stderr
        
@@ -104,6 +108,10 @@
 
 You now have all your executables available as simple to read
 Haskell functions.
+
+If you want to check that all the dependenies still exist, you can use
+`missingExecutables :: IO [String]`, which will tell you if anything is
+missing.
 
 ### Usage in GHCi
 
diff --git a/app/Example.hs b/app/Example.hs
--- a/app/Example.hs
+++ b/app/Example.hs
@@ -11,5 +11,11 @@
 
 $(loadEnv)
 
+-- We could also have been a little more explicit about it.
+-- load ["sleep", "echo", "cat"]
+
 main :: IO ()
-main = (sleep 1 >> echo "Hello" >> sleep 2) |> cat
+main = do
+    -- Crash the program if we are missing any executables.
+    [] <- missingExecutables
+    (sleep 1 >> echo "Hello" >> sleep 2) |> cat
diff --git a/shh.cabal b/shh.cabal
--- a/shh.cabal
+++ b/shh.cabal
@@ -1,5 +1,5 @@
 name:                shh
-version:             0.1.0.1
+version:             0.1.1.0
 synopsis:            Simple shell scripting from Haskell
 description:         Provides a shell scripting environment for Haskell. It
                      helps you all external binaries, and allows you to
@@ -22,16 +22,17 @@
 library
   exposed-modules:     Shh
                      , Shh.Internal
-  build-depends:       base >=4.9 && <4.13
-                     , async
-                     , deepseq
-                     , directory
-                     , filepath
-                     , mtl
-                     , process
-                     , split
-                     , template-haskell
-                     , unix
+  build-depends:
+    base             >= 4.11 && < 4.13,
+    async            >= 2.2.1 && < 2.3,
+    deepseq          >= 1.4.3 && < 1.5,
+    directory        >= 1.3.1 && < 1.4,
+    filepath         >= 1.4.2 && < 1.5,
+    mtl              >= 2.2.2 && < 2.3,
+    process          >= 1.6.3 && < 1.7,
+    split            >= 0.2.3 && < 0.3,
+    template-haskell >= 2.13.0 && < 2.15,
+    unix             >= 2.7.2 && < 2.8
   hs-source-dirs:      src
   default-language:    Haskell2010
   ghc-options: -Wall
diff --git a/src/Shh.hs b/src/Shh.hs
--- a/src/Shh.hs
+++ b/src/Shh.hs
@@ -53,7 +53,9 @@
     -- | == Constructing Arguments
     , ExecArg(..)
     -- | == Template Haskell helpers
+    , load
     , loadEnv
+    , loadAnnotated
     , loadAnnotatedEnv
     , loadExe
     , loadExeAs
diff --git a/src/Shh/Internal.hs b/src/Shh/Internal.hs
--- a/src/Shh/Internal.hs
+++ b/src/Shh/Internal.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE GADTs #-}
 
@@ -19,9 +20,9 @@
 import Data.Char (isLower, isSpace, isAlphaNum)
 import Data.List (nub, dropWhileEnd, intercalate)
 import Data.List.Split (endBy, splitOn)
-import Data.Maybe (mapMaybe)
+import Data.Maybe (mapMaybe, isJust)
 import Language.Haskell.TH
-import System.Directory (doesDirectoryExist, getDirectoryContents)
+import qualified System.Directory as Dir
 import System.Environment (getEnv)
 import System.Exit (ExitCode(..))
 import System.IO
@@ -379,8 +380,9 @@
 pathBins :: IO [FilePath]
 pathBins = do
     pathsVar <- splitOn ":" <$> getEnv "PATH"
-    paths <- filterM doesDirectoryExist pathsVar
-    nub . concat <$> mapM getDirectoryContents paths
+    paths <- filterM Dir.doesDirectoryExist pathsVar
+    ps <- nub . concat <$> mapM Dir.getDirectoryContents paths
+    filterM checkExecutable ps
 
 -- | Execute the given command. Further arguments can be passed in.
 --
@@ -409,6 +411,8 @@
         typn = mkName "a"
         typ = SigD name (ForallT [PlainTV typn] [AppT (ConT ''Unit) (VarT typn), AppT (ConT ''ExecArgs) (VarT typn)] (VarT typn))
     in do
+        isExe <- runIO $ checkExecutable executable
+        when (not isExe) $ error $ "Attempted to load '" ++ executable ++ "', but it isn't executable"
         i <- impl
         return $ [typ,i]
 
@@ -428,23 +432,45 @@
 
 -- | Scans your '$PATH' environment variable and creates a function for each
 -- executable found. Binaries that would not create valid Haskell identifiers
--- are ignored.
+-- are ignored. It also creates the IO action @missingExecutables@ which will
+-- do a runtime check to ensure all the executables that were found at
+-- compile time still exist.
 loadEnv :: Q [Dec]
 loadEnv = loadAnnotatedEnv id
 
--- | Like `loadEnv`, but allows you to modify the function name that would
--- be generated.
-loadAnnotatedEnv :: (String -> String) -> Q [Dec]
-loadAnnotatedEnv f = do
-    bins <- runIO pathBins
+-- | Test to see if an executable can be found either on the $PATH or absolute.
+checkExecutable :: FilePath -> IO Bool
+checkExecutable = fmap isJust . Dir.findExecutable
+
+-- | Load the given executables into the program, checking their executability
+-- and creating a function @missingExecutables@ to do a runtime check for their
+-- availability.
+load :: [String] -> Q [Dec]
+load = loadAnnotated id
+
+-- | Same as `load`, but allows you to modify the function names.
+loadAnnotated :: (String -> String) -> [String] -> Q [Dec]
+loadAnnotated f bins = do
     let pairs = mapMaybe getAnnotation bins
-    fmap join $ mapM (uncurry loadExeAs) pairs
+    ds <- fmap join $ mapM (uncurry loadExeAs) pairs
+    d <- valD (varP (mkName "missingExecutables")) (normalB [|
+                filterM (fmap not . checkExecutable) bins
+            |]) []
 
+    pure (d:ds)
+
     where
         getAnnotation :: String -> Maybe (String,String)
         getAnnotation s
             | validIdentifier (f s) = Just (f s, s)
             | otherwise             = Nothing
+
+-- | Like `loadEnv`, but allows you to modify the function name that would
+-- be generated.
+loadAnnotatedEnv :: (String -> String) -> Q [Dec]
+loadAnnotatedEnv f = do
+    bins <- runIO pathBins
+    loadAnnotated f bins
 
 -- | Function that splits '\0' seperated list of strings. Useful in conjuction
 -- with @find . "-print0"@.
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -55,7 +55,7 @@
         r @?= "test\n"
     , testCase "Lazy read" $ do
         withRead (cat "/dev/urandom" |> xxd) $ \s -> do
-            take 10 s @?= "00000000: "
+            take 6 s @?= "000000"
     , testCase "Multiple outputs" $ do
         l <- readProc $ (echo (1 :: Int) >> echo (2 :: Int)) |> cat
         l @?= "1\n2\n"
