diff --git a/core-program.cabal b/core-program.cabal
--- a/core-program.cabal
+++ b/core-program.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           core-program
-version:        0.3.1.0
+version:        0.3.2.0
 synopsis:       Opinionated Haskell Interoperability
 description:    A library to help build command-line programs, both tools and
                 longer-running daemons.
diff --git a/lib/Core/Program/Context.hs b/lib/Core/Program/Context.hs
--- a/lib/Core/Program/Context.hs
+++ b/lib/Core/Program/Context.hs
@@ -35,6 +35,7 @@
     getContext,
     fmapContext,
     subProgram,
+    Boom(..),
 ) where
 
 import Chrono.TimeStamp (TimeStamp, getCurrentTimeNanoseconds)
@@ -523,3 +524,11 @@
         case target == codenameFrom exporter of
             False -> lookupExporter target exporters
             True -> Just exporter
+
+{-|
+A utility exception for those occasions when you just need to go "boom".
+-}
+data Boom = Boom
+  deriving Show
+
+instance Exception Boom
diff --git a/lib/Core/Program/Execute.hs b/lib/Core/Program/Execute.hs
--- a/lib/Core/Program/Execute.hs
+++ b/lib/Core/Program/Execute.hs
@@ -94,6 +94,7 @@
     unProgram,
     unThread,
     invalid,
+    Boom(..),
     loopForever,
 ) where
 
@@ -145,8 +146,12 @@
 import Core.Text.Rope
 import qualified Data.ByteString as B (hPut)
 import qualified Data.ByteString.Char8 as C (singleton)
+import qualified Data.List as List (intersperse)
 import GHC.Conc (getNumProcessors, numCapabilities, setNumCapabilities)
 import GHC.IO.Encoding (setLocaleEncoding, utf8)
+import System.Directory (
+    findExecutable
+ )
 import System.Exit (ExitCode (..))
 import qualified System.Posix.Process as Posix (exitImmediately)
 import System.Process.Typed (closed, proc, readProcess, setStdin)
@@ -551,6 +556,12 @@
 inputEntire :: Handle -> Program τ Bytes
 inputEntire handle = liftIO (hInput handle)
 
+data ProcessProblem
+    = CommandNotFound Rope
+    deriving (Show)
+
+instance Exception ProcessProblem
+
 {- |
 Execute an external child process and wait for its output and result. The
 command is specified first and and subsequent arguments as elements of the
@@ -578,17 +589,24 @@
 execProcess :: [Rope] -> Program τ (ExitCode, Rope, Rope)
 execProcess [] = error "No command provided"
 execProcess (cmd : args) =
-    let cmdStr = fromRope cmd
-        argsStr = fromRope <$> args
-        task = proc cmdStr argsStr
-        task' = setStdin closed task
+    let cmd' = fromRope cmd
+        args' = fmap fromRope args
+        task = proc cmd' args'
+        task1 = setStdin closed task
+        command = mconcat (List.intersperse (singletonRope ' ') (cmd : args))
      in do
-            debugS "command" task'
+            debug "command" command
 
-            (exit, out, err) <- liftIO $ do
-                readProcess task'
+            probe <- liftIO $ do
+                findExecutable cmd'
+            case probe of
+                Nothing -> do
+                    throw (CommandNotFound cmd)
+                Just _ -> do
+                    (exit, out, err) <- liftIO $ do
+                        readProcess task1
 
-            return (exit, intoRope out, intoRope err)
+                    pure (exit, intoRope out, intoRope err)
 
 {- |
 A thread for concurrent computation. Haskell uses green threads: small lines
diff --git a/lib/Core/Program/Logging.hs b/lib/Core/Program/Logging.hs
--- a/lib/Core/Program/Logging.hs
+++ b/lib/Core/Program/Logging.hs
@@ -3,7 +3,6 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# OPTIONS_GHC -Wno-deprecations #-}
 {-# OPTIONS_HADDOCK prune #-}
 
 {- |
diff --git a/lib/Core/Program/Signal.hs b/lib/Core/Program/Signal.hs
--- a/lib/Core/Program/Signal.hs
+++ b/lib/Core/Program/Signal.hs
@@ -1,5 +1,4 @@
 {-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
-{-# OPTIONS_GHC -Wno-deprecations #-}
 
 module Core.Program.Signal (
     setupSignalHandlers,
