diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,4 @@
+0.1.0.0
+-------
+
+* Initial release
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+Copyright (c) 2016 Galois, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,29 @@
+config-value-getopt
+===================
+
+The config-value-getopt package allows GetOpt[1] specified options
+to be loaded from a configuration file in the config-value[2] format.
+
+* config-value section names are matched against the "long" option names
+in GetOpt.
+* Argument values can be provided as strings or numbers
+* An option will be omitted if its value is set to `no`
+* An option's argument will be omitted if its value is set to `yes`
+
+Example:
+
+```
+address:       "::"
+port:          9000
+no-access-log: yes
+hostname:      no
+```
+
+translates to
+
+```
+--address="::" --port="9000" --no-access-log
+```
+
+1. https://hackage.haskell.org/package/base-4.8.2.0/docs/System-Console-GetOpt.html
+2. https://hackage.haskell.org/package/config-value
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/config-value-getopt.cabal b/config-value-getopt.cabal
new file mode 100644
--- /dev/null
+++ b/config-value-getopt.cabal
@@ -0,0 +1,31 @@
+name:                config-value-getopt
+version:             0.1.0.0
+synopsis:            Interface between config-value and System.GetOpt
+description:         This package allows to set command line configuration
+                     options from a file using the config-value syntax.
+license:             MIT
+license-file:        LICENSE
+author:              Eric Mertens
+maintainer:          emertens@galois.com
+copyright:           2016 Galois, Inc.
+category:            Configuration
+build-type:          Simple
+cabal-version:       >=1.10
+homepage:            https://github.com/GaloisInc/config-value-getopt
+bug-reports:         https://github.com/GaloisInc/config-value-getopt/issues
+
+extra-source-files:
+  README.md
+  CHANGELOG.md
+
+source-repository head
+  type: git
+  location: https://github.com/GaloisInc/config-value-getopt
+
+library
+  exposed-modules:     Config.GetOpt
+  build-depends:       base >=4.8 && <4.10,
+                       text >=1.2.1.3 && <1.3,
+                       config-value >=0.4 && <0.5
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Config/GetOpt.hs b/src/Config/GetOpt.hs
new file mode 100644
--- /dev/null
+++ b/src/Config/GetOpt.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Config.GetOpt (configValueGetOpt) where
+
+import Config
+
+import Data.Either (partitionEithers)
+import Data.Foldable (find)
+import Data.Tuple (swap)
+import Data.Maybe (mapMaybe)
+import System.Console.GetOpt
+import qualified Data.Text as Text
+
+-- | Process the given list of options using a configuration 'Value'.
+-- The configuration value must be a section map. The section names
+-- correspond to the long-names of the options.
+--
+-- Arguments with required parameters should have the option value
+-- follow immediately. To omit a parameter to an option, set it to `yes`.
+--
+-- To omit an option entirely, set it to `no` or remove it from the file.
+--
+-- Options can be provided as decimal literals or string literals.
+configValueGetOpt :: [OptDescr a] -> Value -> ([a], [String])
+configValueGetOpt descrs (Sections sections) =
+  swap (partitionEithers (mapMaybe (sectionToOpts descrs) sections))
+configValueGetOpt _ _ = ([],["invalid configuration value"])
+
+sectionToOpts :: [OptDescr a] -> Section -> Maybe (Either String a)
+sectionToOpts descrs (Section k (Atom "no")) = Nothing
+sectionToOpts descrs (Section k v) = Just $
+  let k' = Text.unpack k in
+  case lookupOption k' descrs of
+    Nothing -> Left (k' ++ ": unknown option")
+    Just o ->
+      case optionArgDescr o of
+        NoArg  x   -> noArg k' v x
+        OptArg f _ -> optArg k' v f
+        ReqArg f _ -> reqArg k' v f
+
+noArg :: String -> Value -> a -> Either String a
+noArg _ (Atom "yes") x = Right x
+noArg k v _ = Left (k ++ ": invalid parameter, expected `yes` or `no`")
+
+optArg :: String -> Value -> (Maybe String -> a) -> Either String a
+optArg _ (Atom "yes") f = Right (f Nothing)
+optArg k v f =
+  case valueString v of
+    Just x -> Right (f (Just x))
+    Nothing -> Left (k ++ ": invalid parameter")
+
+reqArg :: String -> Value -> (String -> a) -> Either String a
+reqArg k v f =
+  case valueString v of
+    Just x -> Right (f x)
+    Nothing -> Left (k ++ ": invalid parameter")
+
+valueString              :: Value -> Maybe String
+valueString (Text t)      = Just (Text.unpack t)
+valueString (Number 10 n) = Just (show n)
+valueString _             = Nothing
+
+lookupOption :: String -> [OptDescr a] -> Maybe (OptDescr a)
+lookupOption name = find $ \o -> name `elem` optionLongNames o
+
+optionLongNames :: OptDescr a -> [String]
+optionLongNames (Option _ names _ _) = names
+
+optionArgDescr :: OptDescr a -> ArgDescr a
+optionArgDescr (Option _ _ arg _) = arg
