diff --git a/AUTHORS.txt b/AUTHORS.txt
new file mode 100644
--- /dev/null
+++ b/AUTHORS.txt
@@ -0,0 +1,3 @@
+Author, target of blame:
+
+Austin Seipp <mad [dot] one [@at] gmail [dot] com>
diff --git a/Development/Shake/CLI.hs b/Development/Shake/CLI.hs
new file mode 100644
--- /dev/null
+++ b/Development/Shake/CLI.hs
@@ -0,0 +1,45 @@
+-- |
+-- Module      : Development.Shake.CLI
+-- Copyright   : (c) Austin Seipp 2012
+-- License     : BSD3
+-- 
+-- Maintainer  : mad.one@gmail.com
+-- Stability   : experimental
+-- Portability : GHC probably
+-- 
+-- This module provides a convenient cmdargs style interface for
+-- controlling shake build options.
+-- 
+module Development.Shake.CLI
+       ( options       -- :: ShakeOptions
+       , shakeWithArgs -- :: Rules () -> IO ()
+       ) where
+import Development.Shake as Shake
+import System.Console.CmdArgs as CA
+
+-- | A 'ShakeOptions' data structure with 
+-- annotations for CmdArgs already included.
+options :: ShakeOptions
+options 
+  = ShakeOptions { shakeFiles     = ".shake" &= help "shake journal/db path"
+                 , shakeThreads   = 1        &= help "threads to use for build" &= name "j" &= typ "NUM"
+                 , shakeVersion   = 1        &= ignore
+                 , shakeStaunch   = False    &= help "keep going after error"  &= name "k"
+                 , shakeReport    = Nothing  &= help "dump profiling report" &= name "prof" &= typFile
+                 , shakeLint      = False    &= help "run build system linter" &= name "lint"
+                 , shakeVerbosity = Shake.Normal &= ignore
+                 }
+    &= verbosity
+    &= helpArg [explicit, name "h", name "help", groupname "Common flags"]
+
+-- | Build a set of Shake rules, and let cmdargs take care of
+-- parsing command line arguments that may influence the used
+-- 'ShakeOptions'
+shakeWithArgs :: Rules () -> IO ()
+shakeWithArgs r = do
+  x <- cmdArgs options
+  v <- CA.getVerbosity
+  case v of
+    CA.Normal -> shake x r
+    CA.Quiet  -> shake (x { shakeVerbosity = Shake.Quiet }) r 
+    CA.Loud   -> shake (x { shakeVerbosity = Shake.Loud }) r
diff --git a/Development/Shake/Imports.hs b/Development/Shake/Imports.hs
new file mode 100644
--- /dev/null
+++ b/Development/Shake/Imports.hs
@@ -0,0 +1,147 @@
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
+{-# LANGUAGE PatternGuards, ScopedTypeVariables #-}
+-- |
+-- Module      : Development.Shake.CLI
+-- Copyright   : (c) Austin Seipp 2012
+-- License     : BSD3
+--
+-- Author      : Soenke Hahn
+-- Maintainer  : mad.one@gmail.com
+-- Stability   : experimental
+-- Portability : GHC probably
+--
+-- Module to search imports. Imports are files that are needed for
+-- compilation of a source code file.  (This module is experimental.)
+module Development.Shake.Imports (
+    -- * declaring rules for imports
+    importsRule,
+    importsDefaultHaskell,
+    importsDefaultCpp,
+    -- * querying imports
+    directImports,
+    transitiveImports,
+  ) where
+
+import Data.List
+import Data.Char
+import Data.Maybe
+
+import Control.Applicative ((<$>))
+import Control.Arrow
+
+import Development.Shake
+import Development.Shake.FilePath
+
+
+-- * querying imports of a file
+
+-- | Searches for imports in a file. Before compiling, you still have to 'need' the imports.
+directImports :: FilePath -> Action [FilePath]
+directImports file =
+    lines <$> readFile' (file <.> "directImports")
+
+-- | Searches for transitive imports in a file. This might be useful for linking.
+transitiveImports :: FilePath -> Action [FilePath]
+transitiveImports file =
+    lines <$> readFile' (file <.> "transitiveImports")
+
+
+-- * declaring rules
+
+-- | @importsRule p searchImports@ registers a rule for how to look up imports
+-- for files matching p.
+importsRule :: (FilePath -> Bool)
+    -> (FilePath -> Action [FilePath])
+    -> Rules ()
+importsRule ruleApplies getDirectDependencies = do
+
+    let isDirectImportKey file =
+            ("//*.directImports" ?== file) &&
+            ruleApplies (dropExtension file)
+
+    isDirectImportKey ?> \ importsFile -> do
+        let sourceFile = dropExtension importsFile
+        directImports' <- getDirectDependencies sourceFile
+        writeFileChanged importsFile (unlines directImports')
+
+    let isTransitiveImportKey file =
+            ("//*.transitiveImports" ?== file) &&
+            ruleApplies (dropExtension file)
+
+    isTransitiveImportKey ?> \ transitiveImportsFile -> do
+        let directImportsFile = replaceExtension transitiveImportsFile ".directImports"
+        directImports' :: [FilePath] <- readFileLines directImportsFile
+        transitiveImports' <- concat <$> mapM readFileLines
+                            (map (<.> ".transitiveImports") directImports')
+        writeFileChanged transitiveImportsFile
+            (unlines $ nub $ directImports' ++ transitiveImports')
+
+    return ()
+
+-- * format specific functions
+
+-- ** haskell source files
+
+-- | Registers a defaultRule for imports in haskell source files (\".hs\").
+-- Only returns the imported files that are found
+-- on disk in one of the directories specified by the first argument.
+importsDefaultHaskell :: [FilePath] -> Rules ()
+importsDefaultHaskell sourceDirs =
+    importsRule ("//*.hs" ?==) (getHaskellDependencies sourceDirs)
+  where
+    getHaskellDependencies :: [FilePath] -> FilePath -> Action [FilePath]
+    getHaskellDependencies source file =
+        readFile' file >>=
+        return . hsImports >>=
+        return . map moduleToFile >>=
+        mapM (searchInPaths source) >>=
+        return . catMaybes
+
+    hsImports :: String -> [String]
+    hsImports xs = [ takeWhile (\z -> isAlphaNum z || z `elem` "._") $ dropWhile (not . isUpper) x
+                   | x <- lines xs, "import " `isPrefixOf` x]
+
+    moduleToFile :: String -> FilePath
+    moduleToFile =
+        map (\ c -> if c == '.' then '/' else c) >>>
+        (<.> "hs")
+
+
+-- ** c++ source files
+
+-- | Registers a defaultRule for imports in C++ source files (\".cpp\").
+-- Only returns the imported files that are found
+-- on disk in one of the directories specified by the first argument.
+importsDefaultCpp :: [FilePath] -> Rules ()
+importsDefaultCpp sourceDirs =
+    importsRule ("//*.cpp" ?==) getDependencies
+  where
+    getDependencies file =
+        readFile' file >>=
+        return . extractLocalIncludes >>=
+        mapM (searchInPaths sourceDirs) >>=
+        return . catMaybes
+
+    extractLocalIncludes :: String -> [FilePath]
+    extractLocalIncludes =
+        lines >>> map localInclude >>> catMaybes
+
+    localInclude :: String -> Maybe FilePath
+    localInclude line |
+        ("#include" : quotedFile : []) <- words line,
+        "\"" `isPrefixOf` quotedFile,
+        "\"" `isSuffixOf` quotedFile
+        = Just $ tail $ init $ quotedFile
+    localInclude _ = Nothing
+
+
+-- * utils
+
+searchInPaths :: [FilePath] -> FilePath -> Action (Maybe FilePath)
+searchInPaths (path : r) file = do
+    exists <- doesFileExist (path </> file)
+    if exists
+        then return $ Just (path </> file)
+        else searchInPaths r file
+searchInPaths [] _ = return Nothing
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,30 @@
+Copyright (c)2012, Austin Seipp
+
+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 Austin Seipp 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,37 @@
+# Extra stuff for the Shake build system.
+
+These modules provide addons for the Shake build system. Right now
+it is quite minimal.
+
+# Installation
+
+Install the latest version of the bindings from Hackage:
+
+    $ cabal install shake-extras
+
+[travis-ci.org](http://travis-ci.org) results: [![Build Status](https://secure.travis-ci.org/thoughtpolice/shake-extras.png?branch=master)](http://travis-ci.org/thoughtpolice/shake-extras)
+
+# Join in
+
+File bugs in the GitHub [issue tracker][].
+
+Master [git repository][gh]:
+
+* `git clone https://github.com/thoughtpolice/shake-extras.git`
+
+There's also a [BitBucket mirror][bb]:
+
+* `git clone https://bitbucket.org/thoughtpolice/shake-extras.git`
+
+# Authors
+
+See [AUTHORS.txt](https://raw.github.com/thoughtpolice/shake-extras/master/AUTHORS.txt).
+
+# License
+
+BSD3. See `LICENSE.txt` for terms of copyright and redistribution.
+
+[main page]: http://thoughtpolice.github.com/shake-extras
+[issue tracker]: http://github.com/thoughtpolice/shake-extras/issues
+[gh]: http://github.com/thoughtpolice/shake-extras
+[bb]: http://bitbucket.org/thoughtpolice/shake-extras
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/shake-extras.cabal b/shake-extras.cabal
new file mode 100644
--- /dev/null
+++ b/shake-extras.cabal
@@ -0,0 +1,56 @@
+name:                shake-extras
+version:             0.1
+synopsis:            Extra utilities for shake build systems
+description:
+  This package is designed to add supporting modules for the Shake
+  build system, that shouldn't be included in the core package.
+homepage:            http://thoughtpolice.github.com/shake-extras
+bug-reports:         http://github.com/thoughtpolice/shake-extras/issues
+license:             BSD3
+license-file:        LICENSE.txt
+copyright:           Copyright (c) Austin Seipp 2012
+author:              Austin Seipp <mad.one@gmail.com>
+maintainer:          Austin Seipp <mad.one@gmail.com>
+category:            Database
+build-type:          Simple
+cabal-version:       >=1.10
+tested-with:         GHC == 7.0.4,
+                     GHC == 7.2.1, GHC == 7.2.2,
+                     GHC == 7.4.1
+
+extra-source-files:
+  AUTHORS.txt README.md
+
+source-repository head
+  type: git
+  location: https://github.com/thoughtpolice/shake-extras.git
+
+library
+  exposed-modules:
+    Development.Shake.CLI
+    Development.Shake.Imports
+  build-depends:
+    base       >= 4 && < 5,
+    filepath,
+    directory,
+    bytestring,
+    shake      == 0.3,
+    cmdargs    >= 0.9
+
+  ghc-options:        -Wall -O2 -funbox-strict-fields
+                      -fwarn-tabs
+  default-extensions: CPP
+  default-language:   Haskell2010
+
+-- test-suite properties
+--   hs-source-dirs: tests
+--   main-is:        Properties.hs
+--   type:           exitcode-stdio-1.0
+-- 
+--   build-depends:
+--     base       >= 4,
+--     shake-extras
+-- 
+--   ghc-options:      -Wall -fno-cse -fno-warn-orphans
+--                     -threaded -rtsopts
+--   default-language: Haskell2010
