diff --git a/doctest/Main.hs b/doctest/Main.hs
new file mode 100644
--- /dev/null
+++ b/doctest/Main.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import Test.DocTest
+
+main :: IO ()
+main = doctest ["-isrc", "src/"]
diff --git a/load-env.cabal b/load-env.cabal
--- a/load-env.cabal
+++ b/load-env.cabal
@@ -1,11 +1,11 @@
--- This file has been generated from package.yaml by hpack version 0.20.0.
+-- This file has been generated from package.yaml by hpack version 0.28.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 9c909afbd1a08e860e60320c5f83c51783e382789593a82de5798a86d1464c45
+-- hash: b1f053dbd45894ad7e296e47dd667ef92f771066b17032b259e2f8d68b156898
 
 name:           load-env
-version:        0.1.2
+version:        0.2.0.0
 synopsis:       Load environment variables from a file.
 description:    Parse a .env file and load any declared variables into the current process's environment. This allows for a .env file to specify development-friendly defaults for configuration values normally set in the deployment environment.
 category:       Configuration
@@ -29,6 +29,7 @@
   build-depends:
       base >=4.8.0 && <5
     , directory
+    , filepath
     , parsec
   exposed-modules:
       LoadEnv
@@ -37,6 +38,19 @@
       Paths_load_env
   default-language: Haskell2010
 
+test-suite doctest
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  other-modules:
+      Paths_load_env
+  hs-source-dirs:
+      doctest
+  ghc-options: -Wall
+  build-depends:
+      base >=4.8.0 && <5
+    , doctest
+  default-language: Haskell2010
+
 test-suite spec
   type: exitcode-stdio-1.0
   main-is: Spec.hs
@@ -49,6 +63,7 @@
     , hspec
     , load-env
     , parsec
+    , temporary
   other-modules:
       LoadEnv.ParseSpec
       LoadEnvSpec
diff --git a/src/LoadEnv.hs b/src/LoadEnv.hs
--- a/src/LoadEnv.hs
+++ b/src/LoadEnv.hs
@@ -1,41 +1,91 @@
+-- |
+--
+-- This is effectively a port of dotenv, whose README explains it best:
+--
+-- /Storing configuration in the environment is one of the tenets of a
+-- twelve-factor app. Anything that is likely to change between deployment
+-- environments–such as resource handles for databases or credentials for
+-- external services–should be extracted from the code into environment
+-- variables./
+--
+-- /But it is not always practical to set environment variables on development
+-- machines or continuous integration servers where multiple projects are run.
+-- dotenv loads variables from a .env file into ENV when the environment is
+-- bootstrapped./
+--
+-- <https://github.com/bkeepers/dotenv>
+--
+-- This library exposes functions for doing just that.
+--
 module LoadEnv
     ( loadEnv
     , loadEnvFrom
+    , loadEnvFromAbsolute
     ) where
 
-
-import Control.Monad (when)
+import Control.Monad ((<=<))
+import Data.Bool (bool)
+import Data.Foldable (for_, traverse_)
+import Data.List (inits)
 import LoadEnv.Parse
-import System.Directory (doesFileExist)
+import System.Directory
+    (doesFileExist, findFile, getCurrentDirectory, makeAbsolute)
 import System.Environment (setEnv)
+import System.FilePath (isRelative, joinPath, splitDirectories)
 import Text.Parsec.String (parseFromFile)
 
--- |
+-- | @'loadEnvFrom' \".env\"@
+loadEnv :: IO ()
+loadEnv = loadEnvFrom ".env"
+
+-- | Parse the given file and set variables in the process's environment
 --
--- Parse @./.env@ for variable declariations. Set those variables in the
--- currently running process's environment. Variables can be declared in the
--- following form:
+-- Variables can be declared in the following form:
 --
 -- > FOO=bar
 -- > FOO="bar"
 -- > FOO='bar'
 --
--- Declarations may optionally be preceded by @export@, which will be ignored.
--- Trailing whitespace is ignored. Quotes inside quoted values or spaces in
--- unquoted values must be escaped with a backlash.
---
--- Invalid lines are silently ignored.
+-- Declarations may optionally be preceded by @\"export \"@, which will be
+-- ignored. Trailing whitespace is ignored. Quotes inside quoted values or
+-- spaces in unquoted values must be escaped with a backlash. Invalid lines are
+-- silently ignored.
 --
--- If you wish to specify your own file, use @'loadEnvFrom'@. If you wish to
--- pass your own string or work with the parse result directly, use the
--- lower-level functions available in @"LoadEnv.Parse"@.
+-- __NOTE__: If the file-name is relative, the directory tree will be traversed
+-- up to @\/@ looking for the file in each parent. Use @'loadEnvFromAbsolute'@
+-- to avoid this.
 --
-loadEnv :: IO ()
-loadEnv = loadEnvFrom ".env"
-
 loadEnvFrom :: FilePath -> IO ()
-loadEnvFrom fp = do
-    e <- doesFileExist fp
+loadEnvFrom name = do
+    mFile <- if isRelative name
+        then flip findFile name . takeDirectories =<< getCurrentDirectory
+        else bool Nothing (Just name) <$> doesFileExist name
 
-    when e $ parseFromFile parseEnvironment fp >>=
-        either print (mapM_ $ uncurry setEnv)
+    for_ mFile $ \file -> do
+        result <- parseFromFile parseEnvironment file
+        either print (traverse_ $ uncurry setEnv) result
+
+-- | @'loadEnvFrom'@, but don't traverse up the directory tree
+loadEnvFromAbsolute :: FilePath -> IO ()
+loadEnvFromAbsolute = loadEnvFrom <=< makeAbsolute
+
+-- | Get all directory names of a directory
+--
+-- Includes itself as the first element of the output.
+--
+-- >>> takeDirectories "/foo/bar/baz"
+-- ["/foo/bar/baz","/foo/bar","/foo","/"]
+--
+-- Leading path-separator is meaningful, and determines if the root directory is
+-- included or not.
+--
+-- >>> takeDirectories "foo/bar/baz"
+-- ["foo/bar/baz","foo/bar","foo"]
+--
+-- Trailing path-separator is not meaningful.
+--
+-- >>> takeDirectories "/foo/bar/baz/"
+-- ["/foo/bar/baz","/foo/bar","/foo","/"]
+--
+takeDirectories :: FilePath -> [FilePath]
+takeDirectories = map joinPath . reverse . drop 1 . inits . splitDirectories
diff --git a/test/LoadEnvSpec.hs b/test/LoadEnvSpec.hs
--- a/test/LoadEnvSpec.hs
+++ b/test/LoadEnvSpec.hs
@@ -4,12 +4,13 @@
 
 import Control.Monad (when)
 import LoadEnv
-import System.Directory (doesFileExist, removeFile)
-import System.Environment (lookupEnv)
+import System.Directory
+import System.Environment
+import System.IO.Temp
 import Test.Hspec
 
 spec :: Spec
-spec = after_ cleanup $
+spec = after_ cleanup $ do
     describe "loadEnv" $ do
         it "loads environment variables from ./.env if present" $ do
             writeFile envFile $ unlines
@@ -29,8 +30,37 @@
 
             return ()
 
+    describe "loadEnvFrom" $ do
+        it "traverses up the directory tree" $ do
+            inTempDirectory $ do
+                writeFile ".env.test" "FOO=\"bar\"\n"
+                inNewDirectory "foo/bar/baz" $ do
+                    loadEnvFrom ".env.test"
+
+            lookupEnv "FOO" `shouldReturn` Just "bar"
+
+    describe "loadEnvFromAbsolute" $ do
+        it "does not traverse up the directory tree" $ do
+            inTempDirectory $ do
+                writeFile ".env.test" "FOO=\"bar\"\n"
+                inNewDirectory "foo/bar/baz" $ do
+                    loadEnvFromAbsolute ".env.test"
+
+            lookupEnv "FOO" `shouldReturn` Nothing
+
+inTempDirectory :: IO a -> IO a
+inTempDirectory f =
+    withSystemTempDirectory "" $ \tmp -> withCurrentDirectory tmp f
+
+inNewDirectory :: FilePath -> IO a -> IO a
+inNewDirectory path f = do
+    createDirectoryIfMissing True path
+    withCurrentDirectory path f
+
 cleanup :: IO ()
 cleanup = do
+    unsetEnv "FOO"
+    unsetEnv "BAR"
     e <- doesFileExist envFile
     when e $ removeFile envFile
 
