diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## sloane 1.8
+
+Use optparse-applicative instead of cmdargs for command line parsing.
+Deprecate '-u', '-?', '-V', '--limit', and '--keys'.
+
 ## sloane 1.7.1 - April 30, 2014
 
 * Clean up the README / man page.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 ---
-title: SLOANE(1) Sloane User Manual | Version 1.7.1
-date: April 30, 2014
+title: SLOANE(1) Sloane User Manual | Version 1.8
+date: May 27, 2014
 ---
 
 # NAME
@@ -10,7 +10,9 @@
 
 # SYNOPSIS
 
-sloane [*options*] *search-terms*
+sloane [-a | --all | -k *keys* | --url] [-n *entries*] *search-terms* ...  
+sloane (--update | --version | --help)  
+sloane
 
 # DESCRIPTION
 
@@ -39,32 +41,32 @@
 
     sloane <FILE | xargs -L1 --verbose sloane
 
-Sloane crops long lines to fit the widths of the terminal. If this is
-unwanted, pipe the output through cat.
+Sloane normally crops long lines to fit the widths of the terminal. If
+this is unwanted, pipe the output through cat.
 
 # OPTIONS
 
--a --all
+-a, --all
 :   Print all fields
 
--k --keys=KEYS
+-k *keys*
 :   Keys of fields to print (default: SN)
 
--n --limit=INT
+--url
+:   Print URLs of found entries (but nothing else)
+
+-n *entries*
 :   Fetch at most this many entries (default: 5)
 
 --update
 :   Update the local sequence cache
 
--u --url
-:   Print URLs of found entries (but nothing else)
+--version
+:   Print version information
 
--? --help
+--help
 :   Display a short help message
 
--V --version
-:   Print version information
-
 # EXAMPLES
 
 The most common search is for entries matching a sequence of consecutive terms:
@@ -81,16 +83,16 @@
 option. For instance, the following search shows the sequence, name,
 comments, and formula fields of the sequence whose A-number is A006531:
 
-    sloane --keys=SNCF id:A006531
+    sloane -k SNCF id:A006531
 
 The next example returns at most 3 results of a free text search:
 
-    sloane -n3 "(2+2)-free posets"
+    sloane -n 3 "(2+2)-free posets"
 
 To view the full entries of these 3 results in a browser (e.g., Firefox)
 one can use the url option:
 
-    firefox `sloane --url -n3 "(2+2)-free posets"`
+    firefox `sloane --url -n 3 "(2+2)-free posets"`
 
 In the final example the local cache is used to filter out sequences
 from the standard input that are in the OEIS:
diff --git a/sloane.1 b/sloane.1
--- a/sloane.1
+++ b/sloane.1
@@ -1,11 +1,20 @@
-.TH "SLOANE" "1" "April 30, 2014" "Sloane User Manual" "Version 1.7.1"
+.TH "SLOANE" "1" "May 27, 2014" "Sloane User Manual" "Version 1.8"
 .SH NAME
 .PP
 sloane \- a command line interface to Sloane\[aq]s On\-Line Encyclopedia
 of Integer Sequences <http://oeis.org>
 .SH SYNOPSIS
 .PP
-sloane [\f[I]options\f[]] \f[I]search\-terms\f[]
+sloane [\-a | \-\-all | \-k \f[I]keys\f[] | \-\-url] [\-n
+\f[I]entries\f[]] \f[I]search\-terms\f[] ...
+.PD 0
+.P
+.PD
+sloane (\-\-update | \-\-version | \-\-help)
+.PD 0
+.P
+.PD
+sloane
 .SH DESCRIPTION
 .PP
 The sloane command searches Sloane\[aq]s On\-Line Encyclopedia of
@@ -51,21 +60,26 @@
 \f[]
 .fi
 .PP
-Sloane crops long lines to fit the widths of the terminal.
+Sloane normally crops long lines to fit the widths of the terminal.
 If this is unwanted, pipe the output through cat.
 .SH OPTIONS
 .TP
-.B \-a \-\-all
+.B \-a, \-\-all
 Print all fields
 .RS
 .RE
 .TP
-.B \-k \-\-keys=KEYS
+.B \-k \f[I]keys\f[]
 Keys of fields to print (default: SN)
 .RS
 .RE
 .TP
-.B \-n \-\-limit=INT
+.B \-\-url
+Print URLs of found entries (but nothing else)
+.RS
+.RE
+.TP
+.B \-n \f[I]entries\f[]
 Fetch at most this many entries (default: 5)
 .RS
 .RE
@@ -75,20 +89,15 @@
 .RS
 .RE
 .TP
-.B \-u \-\-url
-Print URLs of found entries (but nothing else)
+.B \-\-version
+Print version information
 .RS
 .RE
 .TP
-.B \-? \-\-help
+.B \-\-help
 Display a short help message
 .RS
 .RE
-.TP
-.B \-V \-\-version
-Print version information
-.RS
-.RE
 .SH EXAMPLES
 .PP
 The most common search is for entries matching a sequence of consecutive
@@ -117,7 +126,7 @@
 .IP
 .nf
 \f[C]
-sloane\ \-\-keys=SNCF\ id:A006531
+sloane\ \-k\ SNCF\ id:A006531
 \f[]
 .fi
 .PP
@@ -125,7 +134,7 @@
 .IP
 .nf
 \f[C]
-sloane\ \-n3\ "(2+2)\-free\ posets"
+sloane\ \-n\ 3\ "(2+2)\-free\ posets"
 \f[]
 .fi
 .PP
@@ -134,7 +143,7 @@
 .IP
 .nf
 \f[C]
-firefox\ `sloane\ \-\-url\ \-n3\ "(2+2)\-free\ posets"`
+firefox\ `sloane\ \-\-url\ \-n\ 3\ "(2+2)\-free\ posets"`
 \f[]
 .fi
 .PP
diff --git a/sloane.cabal b/sloane.cabal
--- a/sloane.cabal
+++ b/sloane.cabal
@@ -1,5 +1,5 @@
 Name:                sloane
-Version:             1.7.1
+Version:             1.8
 Synopsis:            A command line interface to Sloane's On-Line Encyclopedia of Integer Sequences
 Description:         A command line interface to Sloane's On-Line Encyclopedia of Integer Sequences.
                      For usage see <http://github.com/akc/sloane>.
@@ -20,7 +20,7 @@
 
 Executable sloane
   Main-is:             sloane.hs
-  Build-depends:       base >=3 && <5, cmdargs >=0.9, HTTP >=4000.0.9, network >=2.4,
+  Build-depends:       base >=3 && <5, optparse-applicative >=0.9, HTTP >=4000.0.9, network >=2.4,
                        bytestring >=0.9, ansi-terminal >=0.6, terminal-size >=0.2,
                        filepath >=1.3, directory >=1.2, stringsearch >=0.3,
                        zlib >=0.5, time >=1.4
diff --git a/sloane.hs b/sloane.hs
--- a/sloane.hs
+++ b/sloane.hs
@@ -1,32 +1,41 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-
 -- |
 -- Copyright   : Anders Claesson 2012-2014
 -- Maintainer  : Anders Claesson <anders.claesson@gmail.com>
 -- License     : BSD-3
 --
-import Prelude hiding (all)
-import qualified Data.ByteString.Char8       as B
-import qualified Data.ByteString.Lazy.Char8  as BL
-import qualified Data.ByteString.Lazy.Search as Search
-import qualified Codec.Compression.GZip      as GZip
-import System.IO (stdin, stderr)
-import System.Directory
-import System.FilePath ((</>))
-import System.Console.ANSI
-import System.Console.CmdArgs
-import System.Console.Terminal.Size (Window(..), size)
-import Data.Time (getCurrentTime, diffUTCTime)
-import Data.Maybe (maybe, fromJust)
-import Control.Monad (when, unless)
-import Network.HTTP
-import Network.URI (parseURI)
+import qualified Codec.Compression.GZip       as GZip
+import           Control.Monad                (unless, when)
+import qualified Data.ByteString.Char8        as B
+import qualified Data.ByteString.Lazy.Char8   as BL
+import qualified Data.ByteString.Lazy.Search  as Search
+import           Data.Maybe                   (fromJust, maybe)
+import           Data.Time                    (diffUTCTime, getCurrentTime)
+import           Network.HTTP
+import           Network.URI                  (parseURI)
+import           Options.Applicative
+import           System.Console.ANSI
+import           System.Console.Terminal.Size (Window (..), size)
+import           System.Directory
+import           System.FilePath              ((</>))
+import           System.IO                    (stderr, stdin)
 
 type OEISEntries = [String]
 type ANumbers = [String]
 type Query = String
 type Keys = String
 
+data Args = Args
+    { all    :: Bool
+    , keys   :: String
+    , limit  :: Int
+    , update :: Bool
+    , url    :: Bool
+    , ver    :: Bool
+    , terms  :: [String]
+    }
+
+version   = "sloane 1.8"
+
 oeisHost  = "http://oeis.org/"
 oeisURL   = oeisHost ++ "search?fmt=text"
 oeisKeys  = "ISTUVWXNDHFYAOEeptoKC"
@@ -46,30 +55,10 @@
     [ "No sequence cache found. You need to run \"sloane --update\""
     ]
 msgOldCache = unlines
-    [ "The sequence cache is more than two weeks old"
+    [ "The sequence cache is more than 100 days old"
     , "You may want to run \"sloane --update\""
     ]
 
-data Sloane = Sloane { all    :: Bool
-                     , keys   :: String
-                     , limit  :: Int
-                     , update :: Bool
-                     , url    :: Bool
-                     , terms  :: [String]
-                     }
-              deriving (Data, Typeable)
-
-sloane = cmdArgsMode $ Sloane
-  { all = False &= name "a" &= help "Print all fields"
-  , keys = "SN" &= typ "KEYS" &= help "Keys of fields to print (default: SN)"
-  , limit = 5 &= name "n" &= help "Fetch at most this many entries (default: 5)"
-  , update = False &= help "Update the local sequence cache"
-  , url = False &= name "u" &= help "Print URLs of found entries"
-  , terms = def &= args &= typ "SEARCH-TERMS"
-  }
-  &= versionArg [summary "sloane 1.7.1"]
-  &= summary "Search Sloane's On-Line Encyclopedia of Integer Sequences"
-
 select :: Keys -> OEISEntries -> OEISEntries
 select ks = filter (\line -> null line || head line `elem` ks)
 
@@ -132,6 +121,9 @@
 isInfixOf :: B.ByteString -> BL.ByteString -> Bool
 isInfixOf q = not . null . Search.indices q
 
+dropPreamble :: BL.ByteString -> BL.ByteString
+dropPreamble = BL.unlines . drop 4 . BL.lines
+
 readCache :: FilePath -> IO BL.ByteString
 readCache home = do
     let name = home </> cacheDir </> cacheFile
@@ -140,10 +132,10 @@
         then do
             c <- getCurrentTime
             m <- getModificationTime name
-            let week = 60*60*24*7
-            let expired = c `diffUTCTime` m > 2*week
+            let day = 60*60*24
+            let expired = c `diffUTCTime` m > 100*day
             when expired $ putErr msgOldCache
-            GZip.decompress `fmap` BL.readFile name
+            (dropPreamble . GZip.decompress) `fmap` BL.readFile name
         else
             error msgNoCache
 
@@ -161,20 +153,39 @@
     cache <- readCache home
     B.getContents >>= mapM_ B.putStrLn . filter (`isInfixOf` cache) . seqs
 
-main = do
-    home <- getHomeDirectory
-    args <- cmdArgsRun sloane
-    let query = unwords $ terms args
-    case (update args, null query) of
-        (True, _) -> updateCache home
-        (_, True) -> filterSeqs home
-        _         -> do
-            ncols <- getWidth
-            hits  <- searchOEIS (limit args) query
-            let pick = if all args then id else select (keys args)
-            unless (null hits) $ do
-                newline
-                if url args
-                    then put (urls hits)
-                    else putEntries (ncols - 10) (pick hits)
-                newline
+args :: Parser Args
+args = Args
+    <$> switch (short 'a' <> long "all" <> help "Print all fields")
+    <*> strOption
+        ( short 'k'
+       <> metavar "KEYS"
+       <> value "SN"
+       <> help "Keys of fields to print [default: SN]" )
+    <*> option
+        ( short 'n'
+       <> metavar "N"
+       <> value 5
+       <> help "Fetch at most this many entries [default: 5]" )
+    <*> switch (long "update" <> help "Update the local sequence cache")
+    <*> switch (long "url" <> help "Print URLs of found entries")
+    <*> switch (hidden <> long "version")
+    <*> many (argument str (metavar "TERMS..."))
+
+sloane :: Args -> IO ()
+sloane (Args all keys n update url True terms) = put version >> newline
+sloane (Args all keys n True   url ver  terms) = getHomeDirectory >>= updateCache
+sloane (Args all keys n update url ver  []   ) = getHomeDirectory >>= filterSeqs
+sloane (Args all keys n update url ver  terms) = do
+    ncols <- getWidth
+    hits  <- searchOEIS n (unwords terms)
+    let pick = if all then id else select keys
+    unless (null hits) $ do
+        newline
+        if url
+            then put (urls hits)
+            else putEntries (ncols - 10) (pick hits)
+        newline
+
+main = execParser (info (h <*> args) (fullDesc <> header version)) >>= sloane
+  where
+    h = abortOption ShowHelpText $ hidden <> long "help"
