diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Release 0.20.0.0, August 30, 2013
+Changes since release 0.18.0.0:
+
+* Remove explicit-exception; use Either instead.
+
 Release 0.18.0.0, August 14, 2013
 Changes since release 0.16.0.0:
 
diff --git a/lib/System/Console/MultiArg.hs b/lib/System/Console/MultiArg.hs
--- a/lib/System/Console/MultiArg.hs
+++ b/lib/System/Console/MultiArg.hs
@@ -157,7 +157,6 @@
   , module System.Console.MultiArg.CommandLine
   , module System.Console.MultiArg.Option
   , module System.Console.MultiArg.Prim
-  , module Control.Monad.Exception.Synchronous
   , module System.Environment
   ) where
 
@@ -165,5 +164,4 @@
 import System.Console.MultiArg.CommandLine
 import System.Console.MultiArg.Option
 import System.Console.MultiArg.Prim
-import Control.Monad.Exception.Synchronous
 import System.Environment
diff --git a/lib/System/Console/MultiArg/Combinator.hs b/lib/System/Console/MultiArg/Combinator.hs
--- a/lib/System/Console/MultiArg/Combinator.hs
+++ b/lib/System/Console/MultiArg/Combinator.hs
@@ -24,7 +24,6 @@
 import Control.Applicative
        ((<$>), (<*>), optional, (<$), (*>), (<|>), many)
 
-import qualified Control.Monad.Exception.Synchronous as Ex
 import System.Console.MultiArg.Prim
   ( Parser, try, approxLongOpt,
     nextWord, pendingShortOptArg, nonOptionPosArg,
@@ -37,6 +36,7 @@
 import Data.Map ((!))
 import Data.Maybe (fromMaybe, mapMaybe)
 import Data.Monoid ( mconcat )
+import Text.Read (readMaybe)
 
 
 -- | @notFollowedBy p@ succeeds only if parser p fails. If p fails,
@@ -89,10 +89,10 @@
 
 -- | Reads in values that are members of Read. Provides a generic
 -- error message if the read fails.
-reader :: Read a => String -> Ex.Exceptional InputError a
-reader s = case reads s of
-  (a, ""):[] -> return a
-  _ -> Ex.throw . ErrorMsg $ "could not parse option argument"
+reader :: Read a => String -> Either InputError a
+reader s = case readMaybe s of
+  Just a -> return a
+  Nothing -> Left . ErrorMsg $ "could not parse option argument"
 
 -- | Reads in values that are members of Read, but the value does not
 -- have to appear on the command line. Provides a generic error
@@ -101,12 +101,12 @@
 optReader
   :: Read a
   => Maybe String
-  -> Ex.Exceptional InputError (Maybe a)
+  -> Either InputError (Maybe a)
 optReader ms = case ms of
   Nothing -> return Nothing
-  Just s -> case reads s of
-    (a, ""):[] -> return (Just a)
-    _ -> Ex.throw . ErrorMsg $ "could not parse option argument"
+  Just s -> case readMaybe s of
+    Just a -> return (Just a)
+    _ -> Left . ErrorMsg $ "could not parse option argument"
 
 -- | Indicates errors when parsing options to arguments.
 data InputError
@@ -215,23 +215,23 @@
     -- option to GNU grep, which requires the user to supply one of
     -- three arguments: @always@, @never@, or @auto@.
 
-  | OptionalArgE (Maybe String -> Ex.Exceptional InputError a)
+  | OptionalArgE (Maybe String -> Either InputError a)
     -- ^ This option takes an optional argument, like
     -- 'OptionalArg'. Parsing of the optional argument might fail.
 
-  | OneArgE (String -> Ex.Exceptional InputError a)
+  | OneArgE (String -> Either InputError a)
     -- ^ This option takes a single argument, like 'OneArg'. Parsing
     -- of the argument might fail.
 
-  | TwoArgE (String -> String -> Ex.Exceptional InputError a)
+  | TwoArgE (String -> String -> Either InputError a)
     -- ^ This option takes two arguments, like 'TwoArg'. Parsing of
     -- the arguments might fail.
 
-  | ThreeArgE (String -> String -> String -> Ex.Exceptional InputError a)
+  | ThreeArgE (String -> String -> String -> Either InputError a)
     -- ^ This option takes three arguments, like 'ThreeArg'. Parsing
     -- of the arguments might fail.
 
-  | VariableArgE ([String] -> Ex.Exceptional InputError a)
+  | VariableArgE ([String] -> Either InputError a)
     -- ^ This option takes a variable number of arguments, like
     -- 'VariableArg'. Parsing of the arguments might fail.
 
@@ -336,28 +336,28 @@
         Just g -> return g
 
     OptionalArgE f -> case maybeArg of
-      Nothing -> Ex.switch (fail . errorMsg (Left lo) []) return
+      Nothing -> either (fail . errorMsg (Left lo) []) return
                  $ f Nothing
-      Just s -> Ex.switch (fail . errorMsg (Left lo) [s]) return
+      Just s -> either (fail . errorMsg (Left lo) [s]) return
                 $ f (Just s)
 
 
     OneArgE f -> maybeNextArg >>= g
       where
-        g a = Ex.switch (fail . errorMsg (Left lo) [a]) return
+        g a = either (fail . errorMsg (Left lo) [a]) return
               $ f a
 
     TwoArgE f -> do
       a1 <- maybeNextArg
       a2 <- nextWord
-      Ex.switch (fail . errorMsg (Left lo) [a1, a2]) return
+      either (fail . errorMsg (Left lo) [a1, a2]) return
         $ f a1 a2
 
     ThreeArgE f -> do
       a1 <- maybeNextArg
       a2 <- nextWord
       a3 <- nextWord
-      Ex.switch (fail . errorMsg (Left lo) [a1, a2, a3]) return
+      either (fail . errorMsg (Left lo) [a1, a2, a3]) return
         $ f a1 a2 a3
 
     VariableArgE f -> do
@@ -365,7 +365,7 @@
       let args = case maybeArg of
             Nothing -> as
             Just a -> a:as
-      Ex.switch (fail . errorMsg (Left lo) args) return
+      either (fail . errorMsg (Left lo) args) return
         $ f args
 
 
@@ -411,7 +411,7 @@
 
 shortVariableArgE
   :: ShortOpt
-  -> ([String] -> Ex.Exceptional InputError a)
+  -> ([String] -> Either InputError a)
   -> Parser a
 shortVariableArgE so f = do
   maybeSameWordArg <- optional pendingShortOptArg
@@ -419,7 +419,7 @@
   let as = case maybeSameWordArg of
         Nothing -> args
         Just a -> a:args
-  Ex.switch (fail . errorMsg (Right so) as) return $ f as
+  either (fail . errorMsg (Right so) as) return $ f as
 
 
 shortOneArg :: (String -> a) -> Parser a
@@ -427,11 +427,11 @@
 
 shortOneArgE
   :: ShortOpt
-  -> (String -> Ex.Exceptional InputError a)
+  -> (String -> Either InputError a)
   -> Parser a
 shortOneArgE so f = do
   a <- firstShortArg
-  Ex.switch (fail . errorMsg (Right so) [a]) return $ f a
+  either (fail . errorMsg (Right so) [a]) return $ f a
 
 firstShortArg :: Parser String
 firstShortArg =
@@ -454,12 +454,12 @@
 
 shortTwoArgE
   :: ShortOpt
-  -> (String -> String -> Ex.Exceptional InputError a)
+  -> (String -> String -> Either InputError a)
   -> Parser a
 shortTwoArgE so f = do
   a1 <- firstShortArg
   a2 <- nextWord
-  Ex.switch (fail . errorMsg (Right so) [a1, a2]) return
+  either (fail . errorMsg (Right so) [a1, a2]) return
     $ f a1 a2
 
 shortThreeArg :: (String -> String -> String -> a) -> Parser a
@@ -467,13 +467,13 @@
 
 shortThreeArgE
   :: ShortOpt
-  -> (String -> String -> String -> Ex.Exceptional InputError a)
+  -> (String -> String -> String -> Either InputError a)
   -> Parser a
 shortThreeArgE so f = do
   a1 <- firstShortArg
   a2 <- nextWord
   a3 <- nextWord
-  Ex.switch (fail . errorMsg (Right so) [a1, a2, a3]) return
+  either (fail . errorMsg (Right so) [a1, a2, a3]) return
     $ f a1 a2 a3
 
 shortOptionalArg :: (Maybe String -> a) -> Parser a
@@ -489,7 +489,7 @@
 
 shortOptionalArgE
   :: ShortOpt
-  -> (Maybe String -> Ex.Exceptional InputError a)
+  -> (Maybe String -> Either InputError a)
   -> Parser a
 shortOptionalArgE so f = do
   maybeSameWordArg <- optional pendingShortOptArg
@@ -497,11 +497,11 @@
     Nothing -> do
       maybeArg <- optional nonOptionPosArg
       case maybeArg of
-        Nothing -> Ex.switch (fail . errorMsg (Right so) []) return
+        Nothing -> either (fail . errorMsg (Right so) []) return
                    $ f Nothing
-        Just a -> Ex.switch (fail . errorMsg (Right so) [a]) return
+        Just a -> either (fail . errorMsg (Right so) [a]) return
                   $ f (Just a)
-    Just a -> Ex.switch (fail . errorMsg (Right so) [a]) return
+    Just a -> either (fail . errorMsg (Right so) [a]) return
               $ f (Just a)
 
 
diff --git a/lib/System/Console/MultiArg/CommandLine.hs b/lib/System/Console/MultiArg/CommandLine.hs
--- a/lib/System/Console/MultiArg/CommandLine.hs
+++ b/lib/System/Console/MultiArg/CommandLine.hs
@@ -45,7 +45,6 @@
 
 import qualified System.Console.MultiArg.Combinator as C
 import qualified System.Console.MultiArg.Prim as P
-import qualified Control.Monad.Exception.Synchronous as Ex
 import System.Environment (getArgs, getProgName)
 import System.Exit (exitFailure, exitSuccess)
 import qualified System.IO as IO
@@ -129,7 +128,7 @@
 data OptsWithPosArgs s a = OptsWithPosArgs
   { opOpts :: Opts s a
   , opIntersperse :: Intersperse
-  , opPosArg :: String -> Ex.Exceptional C.InputError a
+  , opPosArg :: String -> Either C.InputError a
   }
 
 instance MapShortcuts OptsWithPosArgs where
@@ -179,7 +178,7 @@
   -> Intersperse
   -- ^ Allow interspersion of mode options and positional arguments?
 
-  -> (String -> Ex.Exceptional C.InputError a)
+  -> (String -> Either C.InputError a)
   -- ^ Parses positional arguments
 
   -> Mode h r
@@ -245,7 +244,7 @@
   -> [String]
   -- ^ The command line arguments to parse
 
-  -> Ex.Exceptional P.Error (Either s [a])
+  -> Either P.Error (Either s [a])
   -- ^ Returns an error if the command line arguments could not be
   -- parsed. If the parse was successful, returns an Either.  A Left
   -- indicates that the user selected a shortcut option.  A Right
@@ -262,7 +261,7 @@
   -- shortcut options.  For instance, @git --help@ contains a single
   -- shortcut option.
 
-  -> ([g] -> Ex.Exceptional String (Either r [Mode s r]))
+  -> ([g] -> Either String (Either r [Mode s r]))
   -- ^ This function processes the global options.  If there are no
   -- shortcut options specified in the global options, it is applied
   -- to the result of processing the global options.  This function
@@ -275,7 +274,7 @@
   -> [String]
   -- ^ Command line arguments to parse
 
-  -> Ex.Exceptional P.Error (Either s r)
+  -> Either P.Error (Either s r)
   -- ^ If the command line arguments fail to parse, this will be an
   -- Exception with the error.  If the parser is successful, this
   -- returns an Either. A Left indicates that the user entered a
@@ -289,8 +288,8 @@
       case eiGs of
         Left spec -> return . Left $ spec
         Right gs -> case process gs of
-          Ex.Exception s -> fail s
-          Ex.Success eiModes -> case eiModes of
+          Left s -> fail s
+          Right eiModes -> case eiModes of
             Left r -> return (Right r)
             Right modes -> parseModes modes
 
@@ -303,7 +302,7 @@
   -> Intersperse
   -- ^ Allow interspersion of options and arguments?
 
-  -> (String -> Ex.Exceptional C.InputError a)
+  -> (String -> Either C.InputError a)
   -- ^ How to parse positional arguments
 
   -> IO [a]
@@ -314,8 +313,8 @@
   let optsWithArgs = OptsWithPosArgs (Opts os []) i getArg
   ss <- getArgs
   case simplePure optsWithArgs ss of
-    Ex.Exception e -> errorAct e
-    Ex.Success g -> case g of
+    Left e -> errorAct e
+    Right g -> case g of
       Left _ ->
         error "simpleIO: should never happen: no shortcut options"
       Right gs -> return gs
@@ -327,8 +326,8 @@
 simpleIOCustomError showErr os = do
   ss <- getArgs
   case simplePure os ss of
-    Ex.Exception e -> showErr e >> exitFailure
-    Ex.Success g -> return g
+    Left e -> showErr e >> exitFailure
+    Right g -> return g
   
 
 -- | A command line parser for multi-mode command lines.  Runs in the
@@ -337,7 +336,7 @@
   :: Opts s g
   -- ^ Specifies global options and global shortcut options
 
-  -> ([g] -> Ex.Exceptional String (Either r [Mode s r]))
+  -> ([g] -> Either String (Either r [Mode s r]))
   -- ^ This function processes the global options.  If there are no
   -- shortcut options specified in the global options, it is applied
   -- to the result of processing the global options.  This function
@@ -356,8 +355,8 @@
 modesIO os ms = do
   ss <- getArgs
   case modesPure os ms ss of
-    Ex.Exception e -> errorAct e
-    Ex.Success g -> return g
+    Left e -> errorAct e
+    Right g -> return g
 
 
 -- | The name of the program that was entered on the command line,
@@ -397,7 +396,7 @@
   -> Intersperse
   -- ^ Allow interspersion of options and positional arguments?
 
-  -> (String -> Ex.Exceptional C.InputError a)
+  -> (String -> Either C.InputError a)
   -- ^ How to parse positional arguments
 
   -> IO [a]
@@ -432,7 +431,7 @@
   -> Intersperse
   -- ^ Allow interspersion of options and positional arguments?
 
-  -> (String -> Ex.Exceptional C.InputError a)
+  -> (String -> Either C.InputError a)
   -- ^ How to parse positional arguments
 
   -> IO [a]
@@ -456,17 +455,17 @@
 
 -- | Parses positional arguments and handles errors with them.
 parsePosArg
-  :: (String -> Ex.Exceptional C.InputError a)
+  :: (String -> Either C.InputError a)
   -> P.Parser a
 parsePosArg p = do
   a <- P.nextWord
   case p a of
-    Ex.Exception e ->
+    Left e ->
       let msg = "invalid positional argument: \"" ++ a ++ "\""
       in case e of
           C.NoMsg -> fail msg
           C.ErrorMsg s -> fail $ msg ++ ": " ++ s
-    Ex.Success g -> return g
+    Right g -> return g
 
 -- | Parses options only, where they are not interspersed with
 -- positional arguments.  Stops parsing only where it encouters a word
@@ -484,7 +483,7 @@
 -- or at the first word that does not look like an option.
 parseStopOpts
   :: P.Parser a
-  -> (String -> Ex.Exceptional C.InputError a)
+  -> (String -> Either C.InputError a)
   -> P.Parser [a]
 parseStopOpts optParser p =
   (++)
@@ -498,7 +497,7 @@
 -- when applied to a string, returns the appropriate type.
 parseIntersperse
   :: P.Parser a
-  -> (String -> Ex.Exceptional C.InputError a)
+  -> (String -> Either C.InputError a)
   -> P.Parser [a]
 parseIntersperse optParser p =
   let pa = Just <$> parsePosArg p
diff --git a/lib/System/Console/MultiArg/Prim.hs b/lib/System/Console/MultiArg/Prim.hs
--- a/lib/System/Console/MultiArg/Prim.hs
+++ b/lib/System/Console/MultiArg/Prim.hs
@@ -74,7 +74,6 @@
     makeLongOpt )
 import Control.Applicative ( Applicative, Alternative, optional )
 import qualified Control.Applicative as A
-import qualified Control.Monad.Exception.Synchronous as Ex
 import qualified Data.Set as Set
 import Data.Set ( Set )
 import qualified Control.Monad
@@ -306,7 +305,7 @@
   -> Parser a
   -- ^ Parser to run
 
-  -> Ex.Exceptional Error a
+  -> Either Error a
   -- ^ Success or failure. Any parser might fail; for example, the
   -- command line might not have any values left to parse. Use of the
   -- 'choice' combinator can lead to a list of failures.
@@ -314,8 +313,8 @@
 parse ss p =
   let s = State "" ss False
       procReply r = case r of
-        Ok x _ _ -> Ex.Success x
-        Fail m -> Ex.Exception m
+        Ok x _ _ -> Right x
+        Fail m -> Left m
   in case runParser p s of
       Consumed r -> procReply r
       Empty r -> procReply r
@@ -472,6 +471,12 @@
   map (Expected . ("long option: --" ++) . unLongOpt)
 
 
+assert :: e -> Bool -> Either e ()
+assert e b = if b then Left e else Right ()
+
+fromMaybe :: e -> Maybe a -> Either e a
+fromMaybe e = maybe (Left e) Right
+
 -- | Examines the next word. If it matches a LongOpt in the set
 -- unambiguously, returns a tuple of the word actually found and the
 -- matching word in the set and the accompanying text after the equal
@@ -486,21 +491,21 @@
         Consumed (Ok (found, opt, arg) (State ps rm'' stop)
                      (err allOpts))
       allOpts = Set.toList ts
-  in Ex.switch ert gd $ do
-    Ex.assert allOpts $ null ps
-    Ex.assert allOpts $ not stop
-    (x, rm') <- Ex.fromMaybe allOpts $ nextW rm
-    (word, afterEq) <- Ex.fromMaybe allOpts $ getLongOption x
-    opt <- Ex.fromMaybe allOpts $ makeLongOpt word
+  in either ert gd $ do
+    assert allOpts $ null ps
+    assert allOpts $ not stop
+    (x, rm') <- fromMaybe allOpts $ nextW rm
+    (word, afterEq) <- fromMaybe allOpts $ getLongOption x
+    opt <- fromMaybe allOpts $ makeLongOpt word
     if Set.member opt ts
       then return (word, opt, afterEq, rm')
       else do
       let p t = word `isPrefixOf` unLongOpt t
           matches = Set.filter p ts
       case Set.toList matches of
-        [] -> Ex.throw allOpts
+        [] -> Left allOpts
         (m:[]) -> return (word, m, afterEq, rm')
-        ls -> Ex.throw ls
+        ls -> Left ls
 
 
 -- | Parses only pending short option arguments. For example, for the
@@ -648,15 +653,15 @@
       gd (act, mtch, rm'') =
         Consumed $ Ok (act, mtch) (State ps rm'' sp) (err allWords)
       allWords = Set.toList set
-  in Ex.switch ert gd $ do
-      Ex.assert allWords $ null ps
-      (x, rm') <- Ex.fromMaybe allWords $ nextW rm
+  in either ert gd $ do
+      assert allWords $ null ps
+      (x, rm') <- fromMaybe allWords $ nextW rm
       let matches = Set.filter p set
           p t = x `isPrefixOf` t
       case Set.toList matches of
-        [] -> Ex.throw allWords
+        [] -> Left allWords
         r:[] -> return (x, r, rm')
-        xs -> Ex.throw xs
+        xs -> Left xs
       
 -- | @manyTill p end@ runs parser p zero or more times until parser
 -- @end@ succeeds. If @end@ succeeds and consumes input, that input is
diff --git a/multiarg.cabal b/multiarg.cabal
--- a/multiarg.cabal
+++ b/multiarg.cabal
@@ -1,5 +1,5 @@
 Name: multiarg
-Version: 0.18.0.0
+Version: 0.20.0.0
 Cabal-version: >=1.8
 Build-Type: Simple
 License: BSD3
@@ -37,7 +37,6 @@
   Build-depends:
       base ==4.6.*
     , containers ==0.5.*
-    , explicit-exception ==0.1.*
 
   hs-source-dirs: lib
 
