diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2009, Will Donnelly
+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 the software nor the names of its 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 HOLDER 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,3 @@
+#!/usr/bin/env runhaskell
+import Distribution.Simple
+main = defaultMain
diff --git a/System/Environment/XDG/BaseDir.hs b/System/Environment/XDG/BaseDir.hs
new file mode 100644
--- /dev/null
+++ b/System/Environment/XDG/BaseDir.hs
@@ -0,0 +1,110 @@
+{-# LANGUAGE CPP #-}
+
+module System.Environment.XDG.BaseDir
+    ( getUserDataDir
+    , getUserDataFile
+    , getUserConfigDir
+    , getUserConfigFile
+    , getUserCacheDir
+    , getUserCacheFile
+    , getSystemDataDirs
+    , getSystemDataFiles
+    , getSystemConfigDirs
+    , getSystemConfigFiles
+    , getAllDataDirs
+    , getAllDataFiles
+    , getAllConfigDirs
+    , getAllConfigFiles
+    ) where
+
+import Data.Maybe         ( fromMaybe )
+import System.FilePath    ( (</>) )
+import System.Environment ( getEnvironment, getEnv )
+import System.IO.Error    ( try )
+import Text.Regex         ( splitRegex, mkRegex, Regex )
+import System.Directory   ( getHomeDirectory )
+import Control.Monad      ( liftM2 )
+
+#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
+
+splitDirs :: String -> [String]
+splitDirs = splitRegex $ mkRegex ";"
+
+getDefault "XDG_DATA_HOME"   = getEnv "AppData"
+getDefault "XDG_CONFIG_HOME" = userRelative $ "Local Settings"
+getDefault "XDG_CACHE_HOME"  = userRelative $ "Local Settings" </> "Cache"
+getDefault "XDG_DATA_DIRS"   = getEnv "ProgramFiles"
+getDefault "XDG_CONFIG_DIRS" = getEnv "ProgramFiles"
+getDefault _                 = return ""
+
+#else
+
+splitDirs :: String -> [String]
+splitDirs = splitRegex $ mkRegex ":"
+
+getDefault "XDG_DATA_HOME"   = userRelative $ ".local" </> "share"
+getDefault "XDG_CONFIG_HOME" = userRelative $ ".config"
+getDefault "XDG_CACHE_HOME"  = userRelative $ ".cache"
+getDefault "XDG_DATA_DIRS"   = return $ "/usr/local/share:/usr/share"
+getDefault "XDG_CONFIG_DIRS" = return $ "/etc/xdg"
+getDefault _                 = return $ ""
+
+#endif
+
+-- | Get the directory for user-specific data files.
+getUserDataDir      :: String -> IO FilePath
+getUserDataDir      = singleDir "XDG_DATA_HOME"
+-- | Get the directory for user-specific configuration files.
+getUserConfigDir    :: String -> IO FilePath
+getUserConfigDir    = singleDir "XDG_CONFIG_HOME"
+-- | Get the directory for user-specific cache files.
+getUserCacheDir     :: String -> IO FilePath
+getUserCacheDir     = singleDir "XDG_CACHE_HOME"
+-- | Get a list of the system-wide data directories.
+getSystemDataDirs   :: String -> IO [FilePath]
+getSystemDataDirs   = multiDirs "XDG_DATA_DIRS"
+-- | Get a list of the system-wide configuration directories.
+getSystemConfigDirs :: String -> IO [FilePath]
+getSystemConfigDirs = multiDirs "XDG_CONFIG_DIRS"
+-- | Get a list of all data directories.
+getAllDataDirs      :: String -> IO [FilePath]
+getAllDataDirs a    = liftM2 (:) (getUserDataDir a) (getSystemDataDirs a)
+-- | Get a list of all configuration directories.
+getAllConfigDirs    :: String -> IO [FilePath]
+getAllConfigDirs a  = liftM2 (:) (getUserConfigDir a) (getSystemConfigDirs a)
+-- | Get the path to a specific user data file.
+getUserDataFile          :: String -> String -> IO FilePath
+getUserDataFile a f      = fmap (</> f) $ getUserDataDir a
+-- | Get the path to a specific user configuration file.
+getUserConfigFile        :: String -> String -> IO FilePath
+getUserConfigFile a f    = fmap (</> f) $ getUserConfigDir a
+-- | Get the path to a specific user cache file.
+getUserCacheFile         :: String -> String -> IO FilePath
+getUserCacheFile a f     = fmap (</> f) $ getUserCacheDir a
+-- | Get a list of all paths for a specific system data file.
+getSystemDataFiles       :: String -> String -> IO [FilePath]
+getSystemDataFiles a f   = fmap (map (</> f)) $ getSystemDataDirs a
+-- | Get a list of all paths for a specific system configuration file.
+getSystemConfigFiles     :: String -> String -> IO [FilePath]
+getSystemConfigFiles a f = fmap (map (</> f)) $ getSystemConfigDirs a
+-- | Get a list of all paths for a specific data file.
+getAllDataFiles          :: String -> String -> IO [FilePath]
+getAllDataFiles a f      = fmap (map (</> f)) $ getAllDataDirs a
+-- | Get a list of all paths for a specific configuration file.
+getAllConfigFiles        :: String -> String -> IO [FilePath]
+getAllConfigFiles a f    = fmap (map (</> f)) $ getAllConfigDirs a
+
+singleDir :: String -> String -> IO FilePath
+singleDir key app = envLookup key >>= return . (</> app)
+
+multiDirs :: String -> String -> IO [FilePath]
+multiDirs key app = envLookup key >>= return . map (</> app) . splitDirs
+
+envLookup :: String -> IO String
+envLookup key = do env <- getEnvironment
+                   case lookup key env of
+                        Just val -> return val
+                        Nothing  -> getDefault key
+
+userRelative :: FilePath -> IO FilePath
+userRelative p = getHomeDirectory >>= return . (</> p)
diff --git a/xdg-basedir.cabal b/xdg-basedir.cabal
new file mode 100644
--- /dev/null
+++ b/xdg-basedir.cabal
@@ -0,0 +1,29 @@
+name:          xdg-basedir
+version:       0.1
+category:      Data
+synopsis:      A basic implementation of the XDG Base Directory specification.
+
+description:   On Unix platforms, this should be a very straightforward
+               implementation of the XDG Base Directory spec. On Windows,
+               it will attempt to do the right thing with regards to
+               choosing appropriate directories.
+
+homepage:      http://github.com/willdonnelly/xdg-basedir
+bug-reports:   http://github.com/willdonnelly/xdg-basedir/issues
+stability:     alpha
+author:        Will Donnelly
+maintainer:    Will Donnelly <will.donnelly@gmail.com>
+copyright:     (c) 2009 Will Donnelly
+license:       BSD3
+license-file:  LICENSE
+
+build-type:    Simple
+cabal-version: >= 1.6
+
+library
+  exposed-modules: System.Environment.XDG.BaseDir
+  build-depends:   base >= 4 && < 5, regex-compat, directory, filepath
+
+source-repository head
+  type:      git
+  location:  git://github.com/willdonnelly/xdg-basedir.git
