diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Revision history for commander-cli
+
+## 0.1.0.0 -- 2020-01-12
+
+* Ported this to a cabal project after having built it in a larger repository
+accompanied by scripts written with it. (Samuel Schlesinger)
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2020 Samuel Schlesinger
+
+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,51 @@
+# Commander
+
+The commander package contains two DSLs for describing command line programs, 
+one at the type level and one at the term level. The one at the type level looks 
+like this:
+
+```haskell
+type File = "writer" & Arg "file" FilePath & Arg "contents" FilePath Raw
+          + "reader" & Arg "file" FilePath & Raw
+```
+
+This is a type which encodes information about an command line program we want to write. We can
+instantiate a term of this type by writing
+
+```haskell
+file :: ProgramT File IO
+file = sub (arg \file -> arg \contents -> raw $ writeFile file contents) 
+   :+: sub (arg \file -> raw $ readFile file >>= putStrLn)
+```
+
+I can write a term of this type without specifying the File type by using the
+TypeApplications extension.
+
+```haskell
+file = sub @"writer" (arg @"file" \file -> arg @"contents" \contents -> raw $ writeFile file contents)
+   :+: sub @"reader" (arg @"file" \file -> raw $ readFile file >>= putStrLn)
+```
+
+The library consists of a few basic types which are important for understanding
+how to use it. The first thing is the class
+
+```haskell
+class Unrender r where
+  unrender :: Text -> Maybe r
+```
+
+This class is what you will use to define the parsing of a type from text and
+can use any parsing library or whatever you want. Next, we have the class
+
+```haskell
+class HasProgram p where
+  data ProgramT p m a
+  run :: ProgramT p IO a -> CommanderT State IO a
+  hoist :: (forall x. m x -> n x) -> ProgramT p m a -> ProgramT p n a
+  invocations :: [Text]
+```
+
+Instances of this class will define a syntactic element, a new instance of the
+data family ProgramT, as well as its semantics in terms of the CommanderT monad,
+which is a backtracking monad based on a metaphor to military commanders which
+retreats upon defeat.
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/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE BlockArguments #-}
+module Main where
+
+import Options.Commander 
+import Prelude
+
+type File = Named "file"
+          & Arg "filename" FilePath 
+          & ("write" & Arg "contents" String & Raw
+          +  "read"  & Raw) 
+
+file :: ProgramT File IO ()
+file = named $ arg \a -> (sub $ arg (raw . writeFile a)) :+: (sub . raw $ readFile a >>= putStrLn)
+
+main :: IO ()
+main = command_ (file :+: usage @File)
diff --git a/commander-cli.cabal b/commander-cli.cabal
new file mode 100644
--- /dev/null
+++ b/commander-cli.cabal
@@ -0,0 +1,32 @@
+cabal-version:       2.4
+-- Initial package description 'commander-cli.cabal' generated by 'cabal
+-- init'.  For further documentation, see
+-- http://haskell.org/cabal/users-guide/
+
+name:                commander-cli
+version:             0.1.0.0
+synopsis:            A command line argument/option parser library built around a monadic metaphor
+description:         A command line argument/option parser library built around a monadic metaphor.
+homepage:            https://github.com/SamuelSchlesinger/commander-cli
+-- bug-reports:
+license:             MIT
+license-file:        LICENSE
+author:              Samuel Schlesinger
+maintainer:          sgschlesinger@gmail.com
+copyright:           2019 Samuel Schlesinger
+category:            System, CLI, Options, Parsing
+extra-source-files:  CHANGELOG.md, README.md
+
+library
+  exposed-modules:     Options.Commander
+  other-extensions:    DeriveFunctor, AllowAmbiguousTypes, PolyKinds, GADTs, TypeOperators, DataKinds
+  build-depends:       base ^>=4.13.0.0, mtl ^>=2.2.2, text ^>=1.2.4.0, unordered-containers ^>=0.2.10.0
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+
+executable commander-cli
+  main-is:             Main.hs
+  other-extensions:    DeriveFunctor, AllowAmbiguousTypes, PolyKinds, GADTs, TypeOperators, DataKinds
+  build-depends:       base ^>=4.13.0.0, mtl ^>=2.2.2, text ^>=1.2.4.0, commander-cli ^>=0.1
+  hs-source-dirs:      app
+  default-language:    Haskell2010
diff --git a/src/Options/Commander.hs b/src/Options/Commander.hs
new file mode 100644
--- /dev/null
+++ b/src/Options/Commander.hs
@@ -0,0 +1,413 @@
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE DataKinds #-}
+module Options.Commander where
+
+import Control.Applicative (Alternative(..))
+import Control.Monad ((<=<))
+import Control.Monad (ap, void)
+import Control.Monad.Trans (MonadIO(..), MonadTrans(..))
+import Data.HashMap.Strict as HashMap
+import Data.HashSet as HashSet
+import Data.Int
+import Data.Proxy (Proxy(..))
+import Data.Text (Text, pack, unpack, stripPrefix, find)
+import Data.Text.Read (decimal, signed)
+import Data.Word
+import GHC.TypeLits (Symbol, KnownSymbol, symbolVal)
+import Numeric.Natural
+import System.Environment (getArgs)
+
+-- | A class for interpreting command line arguments into Haskell types.
+class Unrender t where
+  unrender :: Text -> Maybe t
+
+instance Unrender String where
+  unrender = Just . unpack
+
+instance Unrender Text where
+  unrender = Just
+
+-- | A useful default unrender for small, bounded data types.
+unrenderSmall :: (Enum a, Bounded a, Show a) => Text -> Maybe a
+unrenderSmall = flip Prelude.lookup [(pack $ show x, x) | x <- [minBound..maxBound]]
+
+instance Unrender () where
+  unrender = unrenderSmall
+
+instance Unrender a => Unrender (Maybe a) where
+  unrender x = justCase x <|> nothingCase x where
+    justCase x = do
+      x' <- stripPrefix "Just " x
+      return (unrender x')
+    nothingCase x = if x == "Nothing" then return Nothing else Nothing
+
+instance (Unrender a, Unrender b) => Unrender (Either a b) where
+  unrender x = leftCase x <|> rightCase x where
+    leftCase  = fmap Left  . unrender <=< stripPrefix "Left "
+    rightCase = fmap Right . unrender <=< stripPrefix "Right "
+
+instance Unrender Bool where
+  unrender = unrenderSmall
+
+newtype WrappedIntegral i = WrappedIntegral { unwrapIntegral :: i }
+  deriving newtype (Num, Real, Ord, Eq, Enum, Integral)
+
+instance Integral i => Unrender (WrappedIntegral i) where
+  unrender = either (const Nothing) h . signed decimal where
+    h (n, "") = Just (fromInteger n)
+    h _ = Nothing
+
+deriving via WrappedIntegral Integer instance Unrender Integer
+deriving via WrappedIntegral Int instance Unrender Int
+deriving via WrappedIntegral Int8 instance Unrender Int8
+deriving via WrappedIntegral Int16 instance Unrender Int16
+deriving via WrappedIntegral Int32 instance Unrender Int32
+deriving via WrappedIntegral Int64 instance Unrender Int64
+
+newtype WrappedNatural i = WrappedNatural { unwrapNatural :: i }
+  deriving newtype (Num, Real, Ord, Eq, Enum, Integral)
+
+instance Integral i => Unrender (WrappedNatural i) where
+  unrender = either (const Nothing) h . decimal where
+    h (n, "") = if n >= 0 then Just (fromInteger n) else Nothing
+    h _ = Nothing 
+
+deriving via WrappedNatural Natural instance Unrender Natural
+deriving via WrappedNatural Word instance Unrender Word
+deriving via WrappedNatural Word8 instance Unrender Word8
+deriving via WrappedNatural Word16 instance Unrender Word16
+deriving via WrappedNatural Word32 instance Unrender Word32
+deriving via WrappedNatural Word64 instance Unrender Word64
+
+instance Unrender Char where
+  unrender = find (const True)
+
+data Arg :: Symbol -> * -> *
+
+data Opt :: Symbol -> Symbol -> * -> *
+
+data Named :: Symbol -> *
+
+data Usage :: * -> *
+
+data (&) :: k -> * -> *
+infixr 4 &
+
+data Raw :: *
+
+data Flag :: Symbol -> *
+
+data a + b
+infixr 2 +
+
+-- | A 'CommanderT' action is a metaphor for a military commander. At each
+-- step, we have a new 'Action' to take, or we could have experienced
+-- 'Defeat', or we can see 'Victory'. While a real life commander
+-- worries about moving his troops around in order to achieve a victory in
+-- battle, a 'CommanderT' worries about iteratively transforming a state 
+-- to find some value. We will deal with the subset of these actions where
+-- every function must decrease the size of the state, as those are the
+-- actions for which this is a monad.
+data CommanderT state m a
+  = Action (state -> m (CommanderT state m a, state))
+  | Defeat
+  | Victory a
+  deriving Functor
+
+-- | We can run a 'CommanderT' action on a state and see if it has
+-- a successful campaign.
+runCommanderT :: Monad m 
+              => CommanderT state m a 
+              -> state 
+              -> m (Maybe a)
+runCommanderT (Action action) state = do
+  (action', state') <- action state
+  m <- runCommanderT action' state'
+  return m
+runCommanderT Defeat _ = return Nothing
+runCommanderT (Victory a) _ = return (Just a)
+
+instance (Monad m) => Applicative (CommanderT state m) where
+  (<*>) = ap
+  pure = Victory
+
+instance MonadTrans (CommanderT state) where
+  lift ma = Action \state -> do
+    a <- ma
+    return (pure a, state)
+
+instance MonadIO m => MonadIO (CommanderT state m) where
+  liftIO ma = Action \state -> do
+    a <- liftIO ma
+    return (pure a, state)
+
+-- Return laws:
+-- Goal: return a >>= k = k a
+-- Proof: return a >>= k 
+--      = Victory a >>= k 
+--      = k a 
+--      = k a
+-- Goal: m >>= return = m
+-- Proof:
+--   Case 1: Defeat >>= return = Defeat
+--   Case 2: Victory a >>= return 
+--         = Victory a
+--   Case 3: Action action >>= return
+--         = Action \state -> do
+--             (action', state') <- action state
+--             return (action' >>= return, state')
+--
+-- Case 3 serves as an inductive proof only if action' is a strictly smaller action
+-- than action!
+--
+--  Bind laws:
+--  Goal: m >>= (\x -> k x >>= h) = (m >>= k) >>= h
+--  Proof: 
+--    Case 1: Defeat >>= _ = Defeat
+--    Case 2: Victory a >>= (\x -> k x >>= f)
+--          = k a >>= f
+--          = (Victory a >>= k) >>= f
+--    Case 3: Action action >>= (\x -> k x >>= h)
+--          = Action \state -> do
+--              (action', state') <- action state
+--              return (action' >>= (\x -> k x >>= h), state')
+--          = Action \state -> do
+--              (action', state') <- action state
+--              return ((action' >>= k) >>= h, state') -- by IH
+--    On the other hand,
+--            (Action action >>= k) >>= h
+--          = Action (\state -> do
+--              (action', state') <- action state
+--              return (action' >>= k, state') >>= h
+--          = Action \state -> do
+--              (action', state') <- action state
+--              return ((action' >>= k) >>= h, state')
+--               
+--   This completes our proof for the case when these are finite.
+--   Basically, we require that the stream an action produces is strictly
+--   smaller than any other streams, for all state inputs. The ways that we
+--   use this monad transformer satisify this constraint. If this
+--   constraint is not met, many of our functions will return bottom.
+--
+--   We can certainly have functions that operate on these things and
+--   change them safely, without violating this constraint. All of the
+--   functions that we define on CommanderT programs preserve this
+--   property.
+--
+--   An example of a violating term might be:
+--
+--   violator :: CommanderT state m
+--   violator = Action (\state -> return (violator, state))
+--
+--   The principled way to include this type would be to parameterize it by
+--   a natural number and have that natural number decrease over time, but
+--   to enforce that in Haskell we couldn't have the monad instance
+--   anyways. This is the way to go for now, despite the type violating the
+--   monad laws potentially for infinite inputs. 
+instance Monad m => Monad (CommanderT state m) where
+  Defeat >>= _ = Defeat
+  Victory a >>= f = f a
+  Action action >>= f = Action \state -> do
+    (action', state') <- action state
+    return (action' >>= f, state')
+
+instance Monad m => Alternative (CommanderT state m) where
+  empty = Defeat 
+  Defeat <|> a = a 
+  v@(Victory _) <|> _ = v
+  Action action <|> p = Action \state -> do
+    (action', state') <- action state 
+    return (action' <|> p, state')
+
+data State = State 
+  { arguments :: [Text]
+  , options :: HashMap Text Text
+  , flags :: HashSet Text }
+
+-- | This is the workhorse of the library and is inspired by the servant
+-- HTTP library. Basically, it allows you to 'run' your 'ProgramT'
+-- representation of your program as a 'CommanderT' and pump the 'State'
+-- through it until you've processed all of the arguments, options, and
+-- flags that you have specified must be used in your 'ProgramT'. You can
+-- think of 'ProgramT' as a useful syntax for command line programs, but
+-- 'CommanderT' as the semantics of that program. We also give the ability
+-- to 'hoist' 'ProgramT' actions between monads if you can uniformly turn
+-- computations in one into another.
+class HasProgram p where
+  data ProgramT p (m :: * -> *) a
+  run :: ProgramT p IO a -> CommanderT State IO a
+  hoist :: (forall x. m x -> n x) -> ProgramT p m a -> ProgramT p n a
+  invocations :: [Text]
+
+instance (Unrender t, KnownSymbol name, HasProgram p) => HasProgram (Arg name t & p) where
+  newtype ProgramT (Arg name t & p) m a = ArgProgramT { unArgProgramT :: t -> ProgramT p m a }
+  run f = Action $ \State{..} -> do
+    case arguments of
+      (x : xs) -> 
+        case unrender x of
+          Just t -> return (run (unArgProgramT f t), State{ arguments = xs, .. })  
+          Nothing -> return (Defeat, State{..})
+      [] -> return (Defeat, State{..})
+  hoist n (ArgProgramT f) = ArgProgramT (hoist n . f)
+  invocations = [(("<" <> pack (symbolVal (Proxy @name)) <> "> ") <>)] <*> invocations @p
+
+instance (HasProgram x, HasProgram y) => HasProgram (x + y) where
+  data ProgramT (x + y) m a = ProgramT x m a :+: ProgramT y m a
+  run (f :+: g) = run f <|> run g
+  hoist n (f :+: g) = hoist n f :+: hoist n g
+  invocations = invocations @x <> invocations @y
+
+infixr 2 :+:
+
+instance HasProgram Raw where
+  newtype ProgramT Raw m a = RawProgramT { unRawProgramT :: m a }
+  run = liftIO . unRawProgramT
+  hoist n (RawProgramT m) = RawProgramT (n m)
+  invocations = [mempty]
+
+instance HasProgram p => HasProgram (Usage p) where
+  data ProgramT (Usage p) m a = UsageProgramT
+  run _ = Action \s -> do
+    liftIO $ do
+      putStrLn "usage:"
+      void . traverse (putStrLn . unpack) $ invocations @p
+    return (Defeat, s)
+  hoist _ _ = UsageProgramT
+  invocations = [mempty]
+
+instance (KnownSymbol name, KnownSymbol option, HasProgram p, Unrender t) => HasProgram (Opt option name t & p) where
+  newtype ProgramT (Opt option name t & p) m a = OptProgramT { unOptProgramT :: Maybe t -> ProgramT p m a }
+  run f = Action $ \State{..} -> do
+    case HashMap.lookup (pack $ symbolVal (Proxy @option)) options of
+      Just opt' -> 
+        case unrender opt' of
+          Just t -> return (run (unOptProgramT f (Just t)), State{..})
+          Nothing -> return (Defeat, State{..})
+      Nothing  -> return (run (unOptProgramT f Nothing), State{..})
+  hoist n (OptProgramT f) = OptProgramT (hoist n . f)
+  invocations = [(("-" <> (pack $ symbolVal (Proxy @option)) <> " <" <> (pack $ symbolVal (Proxy @name)) <> "> ") <>)  ] <*> invocations @p
+
+instance (KnownSymbol flag, HasProgram p) => HasProgram (Flag flag & p) where
+  newtype ProgramT (Flag flag & p) m a = FlagProgramT { unFlagProgramT :: Bool -> ProgramT p m a }
+  run f = Action $ \State{..} -> do
+    let presence = HashSet.member (pack (symbolVal (Proxy @flag))) flags
+    return (run (unFlagProgramT f presence), State{..})
+  hoist n = FlagProgramT . fmap (hoist n) . unFlagProgramT
+  invocations = [(("~" <> (pack $ symbolVal (Proxy @flag)) <> " ") <>)] <*> invocations @p
+
+instance (KnownSymbol name, HasProgram p) => HasProgram (Named name & p) where
+  newtype ProgramT (Named name &p) m a = NamedProgramT { unNamedProgramT :: ProgramT p m a }
+  run = run . unNamedProgramT 
+  hoist n = NamedProgramT . hoist n . unNamedProgramT
+  invocations = [((pack (symbolVal (Proxy @name)) <> " ") <>)] <*> invocations @p
+
+instance (KnownSymbol seg, HasProgram p) => HasProgram (seg & p) where
+  newtype ProgramT (seg & p) m a = SegProgramT { unSegProgramT :: ProgramT p m a }
+  run s = Action $ \State{..} -> do 
+    case arguments of
+      (x : xs) -> 
+        if x == pack (symbolVal $ Proxy @seg) 
+          then return (run $ unSegProgramT s, State{arguments = xs, ..})
+          else return (Defeat, State{..})
+      [] -> return (Defeat, State{..})
+  hoist n = SegProgramT . hoist n . unSegProgramT
+  invocations = [((pack $ symbolVal (Proxy @seg) <> " ") <> )] 
+            <*> invocations @p
+
+-- | A simple default for getting out the arguments, options, and flags
+-- using 'System.Environment'. We use the syntax ~flag for flags and ~opt
+-- for options, with arguments using the typical ordered representation.
+initialState :: IO State
+initialState = do
+  args <- getArgs
+  let (opts, args', flags) = takeOptions args
+  return $ State args' (HashMap.fromList opts) (HashSet.fromList flags) 
+    where
+      takeOptions :: [String] -> ([(Text, Text)], [Text], [Text])
+      takeOptions = go [] [] [] where
+        go opts args flags (('~':x') : z) = go opts args (pack x' : flags) z
+        go opts args flags (('-':x) : y : z) = go ((pack x, pack y) : opts) args flags z
+        go opts args flags (x : y) = go opts (pack x : args) flags y
+        go opts args flags [] = (opts, reverse args, flags)
+
+-- | This is a combinator which runs a 'ProgramT' with the options,
+-- arguments, and flags that I get using the 'initialState' function,
+-- ignoring the output of the program.
+command_ :: HasProgram p 
+         => ProgramT p IO a 
+         -> IO ()
+command_ prog = void $ initialState >>= runCommanderT (run prog)
+
+-- | This is a combinator which runs a 'ProgramT' with the options,
+-- arguments, and flags that I get using the 'initialState' function,
+-- returning 'Just' the output of the program upon successful option and argument
+-- parsing and returning 'Nothing' otherwise.
+command :: HasProgram p 
+        => ProgramT p IO a 
+        -> IO (Maybe a)
+command prog = initialState >>= runCommanderT (run prog)
+
+-- | Argument combinator
+arg :: KnownSymbol name
+    => (x -> ProgramT p m a) 
+    -> ProgramT (Arg name x & p) m a 
+arg = ArgProgramT
+
+-- | Option combinator
+opt :: (KnownSymbol option, KnownSymbol name)
+    => (Maybe x -> ProgramT p m a) 
+    -> ProgramT (Opt option name x & p) m a
+opt = OptProgramT
+
+-- | Raw monadic combinator
+raw :: m a 
+    -> ProgramT Raw m a
+raw = RawProgramT
+
+-- | Subcommand combinator
+sub :: KnownSymbol s 
+    => ProgramT p m a 
+    -> ProgramT (s & p) m a
+sub = SegProgramT
+
+-- | Named command combinator, should only really be used at the top level.
+named :: KnownSymbol s 
+      => ProgramT p m a 
+      -> ProgramT (Named s & p) m a
+named = NamedProgramT
+
+-- | Boolean flag combinator
+flag :: KnownSymbol f 
+     => (Bool -> ProgramT p m a) 
+     -> ProgramT (Flag f & p) m a
+flag = FlagProgramT
+
+-- | A convenience combinator that constructs the program I often want
+-- to run out of a program I want to write.
+toplevel :: forall s p m a. (HasProgram p, KnownSymbol s, MonadIO m) 
+         => ProgramT p m a 
+         -> ProgramT (Named s & ("help" & Usage (Named s & p) + p)) m a
+toplevel p = named (sub usage :+: p) where
+
+-- | A meta-combinator that takes a type-level description of a command 
+-- line program and produces a simple usage program.
+usage :: HasProgram p => ProgramT (Usage p) m a
+usage = UsageProgramT
