diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+# Change log
+
+Autoexporter uses [Semantic Versioning][].
+The change log is available through the [releases on GitHub][].
+
+[Semantic Versioning]: http://semver.org/spec/v2.0.0.html
+[releases on GitHub]: https://github.com/tfausak/autoexporter/releases
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,23 @@
+[The MIT License (MIT)][]
+
+Copyright (c) 2016 Taylor Fausak
+
+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.
+
+[The MIT License (MIT)]: https://opensource.org/licenses/MIT
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,78 @@
+# [Autoexporter][]
+
+Autoexporter automatically re-exports Haskell modules.
+
+[![Version badge][]][version]
+
+-   [Install](#install)
+-   [Use](#use)
+
+## Install
+
+1.  Install [Stack][].
+
+2.  `stack install autoexporter`
+
+## Use
+
+Let's say you have a module `M` that just exports some other modules. It might
+look like this:
+
+``` haskell
+module M
+    ( module M.A
+    , module M.B
+    ) where
+
+import M.A
+import M.B
+```
+
+This code is error-prone. If you add a new module, say `M.C`, you have to
+remember to come back to this file and re-export it. And this code is tedious
+to write. You have to list each module twice. You can do a little better, but
+not much.
+
+``` haskell
+module M (module X) where
+import M.A as X
+import M.B as X
+```
+
+Now you don't have to write every module twice, but you still have to remember
+to re-export everything. And the generated documentation for this module
+doesn't include anything about the exported modules.
+
+Autoexporter handles this for you. Instead of either of the above approaches,
+simply drop this into the `M` module:
+
+``` haskell
+{-# OPTIONS_GHC -F -pgmF autoexporter #-}
+```
+
+That will generate code like the first example. A couple caveats:
+
+-   Your source files must be rooted in a directory called `library`.
+
+    -   I will happily accept patches that lift this restriction. This is good
+        enough for my purposes now, but it's pretty bad in general. The hard
+        part of this problem is knowing when to stop when converting a file
+        path into a module name. For example, how can we reliably convert
+        `/home/taylor/HSPackage/Data/Package.hs` into `Data.Package`?
+
+-   Absolutely nothing else can be in the source file. Autoexporter will blow
+    up if it finds anything else.
+
+-   Only immediate children will be re-exported. If you use this in some module
+    `M`, it won't pull in `M.A.B`.
+
+-   You cannot selectively leave out any modules. You also cannot selectively
+    exclude any imports from any of the modules.
+
+    -   This could be allowed via `-optF`. I will happily accept patches for
+        this as well.
+
+[Autoexporter]: https://github.com/tfausak/autoexporter
+[Version badge]: https://www.stackage.org/package/autoexporter/badge/nightly?label=version
+[version]: https://www.stackage.org/package/autoexporter
+[Stack]: http://haskellstack.org
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+import qualified Distribution.Simple
+
+main :: IO ()
+main = Distribution.Simple.defaultMain
diff --git a/autoexporter.cabal b/autoexporter.cabal
new file mode 100644
--- /dev/null
+++ b/autoexporter.cabal
@@ -0,0 +1,39 @@
+name: autoexporter
+version: 0.1.0
+cabal-version: >=1.10
+build-type: Simple
+license: MIT
+license-file: LICENSE.md
+maintainer: Taylor Fausak
+synopsis: Automatically re-export modules.
+description:
+    Autoexporter automatically re-exports modules.
+category: Utility
+extra-source-files:
+    CHANGELOG.md
+    README.md
+    stack.yaml
+
+source-repository head
+    type: git
+    location: https://github.com/tfausak/autoexporter
+
+library
+    exposed-modules:
+        Autoexporter
+    build-depends:
+        base >=4.7 && <4.9,
+        directory >=1.2 && <1.3,
+        filepath >=1.3 && <1.5
+    default-language: Haskell2010
+    hs-source-dirs: library
+    ghc-options: -Wall
+
+executable autoexporter
+    main-is: Main.hs
+    build-depends:
+        base -any,
+        autoexporter -any
+    default-language: Haskell2010
+    hs-source-dirs: executable
+    ghc-options: -Wall
diff --git a/executable/Main.hs b/executable/Main.hs
new file mode 100644
--- /dev/null
+++ b/executable/Main.hs
@@ -0,0 +1,4 @@
+import qualified Autoexporter
+
+main :: IO ()
+main = Autoexporter.main
diff --git a/library/Autoexporter.hs b/library/Autoexporter.hs
new file mode 100644
--- /dev/null
+++ b/library/Autoexporter.hs
@@ -0,0 +1,43 @@
+module Autoexporter where
+
+import qualified Data.List as List
+import qualified System.Directory as Directory
+import qualified System.Environment as Environment
+import qualified System.FilePath as FilePath
+
+main :: IO ()
+main = do
+    args <- Environment.getArgs
+    case args of
+        [name, inputFile, outputFile] -> do
+            input <- readFile inputFile
+            case input of
+                "{-# OPTIONS_GHC -F -pgmF nafta #-}\n" -> do
+                    let moduleName = makeModuleName name
+
+                    let directory = FilePath.dropExtension inputFile
+                    files <- Directory.getDirectoryContents directory
+                    let haskellFiles = filter (\ f -> List.isSuffixOf ".hs" f || List.isSuffixOf ".lhs" f) files
+                    let paths = map (directory FilePath.</>) haskellFiles
+                    let modules = List.sort (map makeModuleName paths)
+                    let exports = init (unlines (map (\ x -> "    module " ++ x ++ ",") modules))
+                    let imports = init (unlines (map ("import " ++) modules))
+
+                    let output = unlines
+                            [ unwords ["module", moduleName, "("]
+                            , exports
+                            , ") where"
+                            , ""
+                            , imports
+                            ]
+                    writeFile outputFile output
+                _ -> error ("unexpected input: " ++ show input)
+        _ -> error ("unexpected arguments: " ++ show args)
+  where
+    makeModuleName :: FilePath -> String
+    makeModuleName name =
+        let path = FilePath.dropExtension name
+            parts = FilePath.splitDirectories path
+            -- TODO: Figure out a better way to get the actual module name.
+            rest = tail (dropWhile (/= "library") parts)
+        in  List.intercalate "." rest
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,1 @@
+resolver: lts-5.3
