diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, Iavor S. Diatchki
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Iavor S. Diatchki nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/simple-get-opt.cabal b/simple-get-opt.cabal
new file mode 100644
--- /dev/null
+++ b/simple-get-opt.cabal
@@ -0,0 +1,26 @@
+name:                simple-get-opt
+version:             0.1.0.0
+synopsis:            A simple library for processing command-line options.
+description:
+  A simple library for processing command-line options.
+  The library captures a common usage pattern of the GetOpt module
+  form the standard libraries.
+
+license:             BSD3
+license-file:        LICENSE
+author:              Iavor S. Diatchki
+maintainer:          iavor.diatchki@gmail.com
+category:            Development
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     SimpleGetOpt
+  build-depends:       base < 10
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: git://github.com/yav/simple-get-opt.git
+
diff --git a/src/SimpleGetOpt.hs b/src/SimpleGetOpt.hs
new file mode 100644
--- /dev/null
+++ b/src/SimpleGetOpt.hs
@@ -0,0 +1,179 @@
+{- | Provides support for processing command-line arguments.
+This is a simple wrapper around get-opt.
+Here is an example of a typical usage:
+
+> data Settings = Settings
+>   { verbose :: Bool
+>   , inPar   :: Int
+>   , files   :: [String]
+>   }
+>
+> options :: OptSpec Settings
+> options = OptSpec
+>   { progDefaults = Settings { verbose = False
+>                             , inPar   = 1
+>                             , files   = []
+>                             }
+>
+>   , progOptions =
+>       [ Option ['v'] ["verbose"]
+>         "Display more information while working."
+>         $ NoArg $ \s -> Right s { verbose = True }
+>
+>       , Option ['p'] ["par"]
+>         "Process that many files at once."
+>         $ ReqArg "NUM" $ \a s ->
+>           case readMaybe a of
+>             Just n | n > 0  -> Right s { inPar = n }
+>             _               -> Left "Invalid value for `par`"
+>       ]
+>
+>   , progParamDocs =
+>       [ ("FILES",   "The files that need processing.") ]
+>
+>   , progParams = \p s -> Right s { files = p : files s }
+>   }
+
+Here is what the usage information looks like:
+
+> *Main> dumpUsage options 
+> Parameters:
+>   FILES    The files that need processing.
+>
+> Flags:
+>   -v      --verbose  Display more information while working.
+>   -p NUM  --par=NUM  Process that many files at once.
+-}
+
+module SimpleGetOpt
+  ( -- * Basic functionality
+    getOpts
+  , OptSpec(..)
+  , OptDescr(..)
+  , OptSetter
+  , ArgDescr(..)
+
+  -- * Information and error reporting.
+  , dumpUsage
+  , reportUsageError
+  , usageString
+  ) where
+
+import qualified System.Console.GetOpt as GetOpt
+import System.IO(stderr,hPutStrLn)
+import System.Exit(exitFailure)
+import System.Environment(getArgs)
+
+import Control.Monad(unless)
+
+
+
+-- | Specification of a collection of options, described by type @a@.
+data OptSpec a = OptSpec
+  { progDefaults :: a
+    -- ^ Default options.
+    -- This is what is used if no other options are provided.
+
+  , progOptions  :: [OptDescr a]
+    -- ^ A list of options and command-line flags.
+
+  , progParamDocs       :: [(String,String)]
+    -- ^ Documentatio for the free-form parameters.
+
+  , progParams      :: String -> OptSetter a
+    -- ^ Add a parameter that is not an option or a flag
+    -- (i.e., this is just a free form command line parameter).
+
+  }
+
+-- | Describe an option.
+data OptDescr a = Option
+  { optShortFlags  :: [Char]
+  , optLongFlags   :: [String]
+  , optDescription :: String
+  , optArgument    :: ArgDescr a
+  }
+
+-- | Manipulate options of type @a@, with support for errors.
+type OptSetter a = a -> Either String a
+
+-- | Describe an option argumnet.
+data ArgDescr a =
+
+    NoArg (OptSetter a)
+    -- ^ This option does not take an argument.
+
+  | ReqArg String (String -> OptSetter a)
+    -- ^ This optoin has a required arugment.
+    -- The string describes the type of the argument.
+
+  | OptArg String (Maybe String -> OptSetter a)
+    -- ^ This optoin has an optional arugment.
+    -- The string describes the type of the argument.
+
+
+opts :: OptSpec a -> [ GetOpt.OptDescr (OptSetter a) ]
+opts = map convertOpt . progOptions
+
+convertArg :: ArgDescr a -> GetOpt.ArgDescr (OptSetter a)
+convertArg arg =
+  case arg of
+    NoArg a    -> GetOpt.NoArg a
+    ReqArg s a -> GetOpt.ReqArg a s
+    OptArg s a -> GetOpt.OptArg a s
+
+convertOpt :: OptDescr a -> GetOpt.OptDescr (OptSetter a)
+convertOpt (Option a b c d) = GetOpt.Option a b (convertArg d) c
+
+
+
+addOpt :: (a, [String]) -> (a -> Either String a) -> (a, [String])
+addOpt (a,es) f = case f a of
+                    Left e   -> (a,e:es)
+                    Right a1 -> (a1,es)
+
+addFile :: (String -> OptSetter a) -> (a, [String]) -> String -> (a,[String])
+addFile add (a,es) file = case add file a of
+                            Left e    -> (a,e:es)
+                            Right a1  -> (a1,es)
+
+
+-- | Get the command-line options and process them according to the given spec.
+-- The options will be permuted to get flags.
+getOpts :: OptSpec a -> IO a
+getOpts os =
+  do as <- getArgs
+     let (funs,files,errs) = GetOpt.getOpt GetOpt.Permute (opts os) as
+     unless (null errs) $ reportUsageError os errs
+     let (a, errs1) = foldl addOpt (progDefaults os,[]) funs
+     unless (null errs1) $ reportUsageError os errs1
+     let (b, errs2) = foldl (addFile (progParams os)) (a,[]) files
+     unless (null errs2) $ reportUsageError os errs2
+     return b
+
+-- | Print the given messages on 'stderr' and show the program's usage info.
+reportUsageError :: OptSpec a -> [String] -> IO b
+reportUsageError os es =
+  do hPutStrLn stderr "Invalid command line options:"
+     hPutStrLn stderr $ unlines $ map ("  " ++) es
+     dumpUsage os
+     exitFailure
+
+-- | Show the program's usage information on 'stderr'.
+dumpUsage :: OptSpec a -> IO ()
+dumpUsage os = hPutStrLn stderr (usageString os)
+
+
+-- | A string descibing the options.
+usageString :: OptSpec a -> String
+usageString os = GetOpt.usageInfo (params ++ "Flags:") (opts os)
+  where
+  params = case concatMap ppParam (progParamDocs os) of
+             "" -> ""
+             ps -> "Parameters:\n" ++ ps ++ "\n"
+
+  ppParam (x,y) = "  " ++ x ++ "    " ++ y ++ "\n"
+
+
+
+
