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/gargoyle-postgresql.cabal b/gargoyle-postgresql.cabal
new file mode 100644
--- /dev/null
+++ b/gargoyle-postgresql.cabal
@@ -0,0 +1,98 @@
+name: gargoyle-postgresql
+version: 0.1
+license: BSD3
+author: Obsidian Systems LLC
+maintainer: maintainer@obsidian.systems
+copyright: Copyright (C) 2017 Obsidian Systems LLC
+category: PostgreSQL
+build-type: Simple
+cabal-version: >=1.10
+synopsis: Manage PostgreSQL servers with gargoyle
+description:
+  This package provides tools for managing PostgreSQL servers that live in local folders and communicate via a Unix domain socket. It uses the <https://hackage.haskell.org/package/gargoyle gargoyle> package in order to automatically initialize, spin up, and spin down such servers according to client demand.
+  .
+  The `gargoyle-psql` executable is such a client which will try to connect to a PostgreSQL server at a given location:
+  .
+  > gargoyle-psql db
+  .
+  > psql (9.5.6)
+  > Type "help" for help.
+  >
+  > postgres=#
+  .
+  Note that `gargoyle-psql` assumes that PostgreSQL executables such as `psql` are available on the PATH. A custom 'Gargoyle' is required to use non-standard PostgreSQL installations.
+  .
+  The following is an example of using this package to run <https://hackage.haskell.org/package/postgresql-simple postgresql-simple> actions using a local DB:
+  .
+  > import Database.PostgreSQL.Simple
+  > import Gargoyle
+  > import Gargoyle.PostgreSQL
+  >
+  > withDb :: String -> (Connection -> IO a) -> IO a
+  > withDb dbPath a = withGargoyle defaultPostgres dbPath $ \dbUri -> a =<< connectPostgreSQL dbUri
+
+-- Requires postgres to be in the environment to run
+flag enable-psql-test
+  default: False
+  manual: True
+
+library
+  exposed-modules: Gargoyle.PostgreSQL
+  ghc-options: -Wall
+  ghc-prof-options: -fprof-auto
+  build-depends: base >= 4.9 && < 4.11
+               , bytestring == 0.10.*
+               , directory == 1.3.*
+               , gargoyle == 0.1.*
+               , process == 1.4.*
+               , stringsearch == 0.3.*
+               , text == 1.2.*
+               , unix == 2.7.*
+  hs-source-dirs: src
+  default-language: Haskell2010
+
+executable gargoyle-psql
+  main-is: gargoyle-psql.hs
+  hs-source-dirs: src-bin
+  ghc-options: -Wall -threaded
+  ghc-prof-options: -fprof-auto
+  default-language: Haskell2010
+  build-depends: base
+               , bytestring
+               , gargoyle
+               , gargoyle-postgresql
+               , process
+               , text
+               , unix
+
+executable gargoyle-postgres-monitor
+  main-is: gargoyle-postgres-monitor.hs
+  hs-source-dirs: src-bin
+  ghc-options: -Wall -threaded
+  ghc-prof-options: -fprof-auto
+  default-language: Haskell2010
+  build-depends: base
+               , bytestring
+               , gargoyle
+               , gargoyle-postgresql
+               , process
+               , text
+
+test-suite gargoyle-psql-test
+  type: exitcode-stdio-1.0
+  main-is: gargoyle-psql-test.hs
+  ghc-options: -Wall -threaded
+  ghc-prof-options: -fprof-auto
+  hs-source-dirs: tests
+  if !flag(enable-psql-test)
+    buildable: False
+  else
+    build-depends: base
+                 , bytestring
+                 , directory
+                 , filepath
+                 , gargoyle
+                 , gargoyle-postgresql
+                 , process
+                 , text
+                 , unix
diff --git a/src-bin/gargoyle-postgres-monitor.hs b/src-bin/gargoyle-postgres-monitor.hs
new file mode 100644
--- /dev/null
+++ b/src-bin/gargoyle-postgres-monitor.hs
@@ -0,0 +1,7 @@
+module Main where
+
+import Gargoyle
+import Gargoyle.PostgreSQL
+
+main :: IO ()
+main = gargoyleMain defaultPostgres
diff --git a/src-bin/gargoyle-psql.hs b/src-bin/gargoyle-psql.hs
new file mode 100644
--- /dev/null
+++ b/src-bin/gargoyle-psql.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Data.List
+import System.Environment
+import System.Exit
+
+import Gargoyle.PostgreSQL
+
+main :: IO ()
+main = do
+  args <- getArgs
+  case args of
+    [dbPath] -> psqlLocal defaultPostgres "psql" dbPath Nothing
+    _ -> do
+      pname <- getProgName
+      putStrLn $ intercalate " "
+        [ "USAGE:", pname, "<path>" ]
+      putStrLn "\t<path>: path to local db"
+      exitFailure
+  return ()
diff --git a/src/Gargoyle/PostgreSQL.hs b/src/Gargoyle/PostgreSQL.hs
new file mode 100644
--- /dev/null
+++ b/src/Gargoyle/PostgreSQL.hs
@@ -0,0 +1,132 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Gargoyle.PostgreSQL where
+
+import Control.Monad
+import Data.ByteString (ByteString)
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.ByteString.Search as BS
+import Data.Function
+import Data.Maybe
+import Data.Monoid
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import System.Directory
+import System.Exit
+import System.IO
+import System.Posix.Signals
+import System.Process
+import System.Process.Internals
+
+import Gargoyle
+
+-- | A 'Gargoyle' that assumes `initdb` and `postgres` are in the path and
+-- will perform a 'fast shutdown' on termination (see below).
+defaultPostgres :: Gargoyle ProcessHandle ByteString
+defaultPostgres = mkPostgresGargoyle "initdb" "postgres" shutdownPostgresFast
+
+-- | Create a gargoyle by telling it where the relevant PostgreSQL executables are and
+-- what it should do in order to shut down the server. This module provides two options:
+-- 'shutdownPostgresSmart' and 'shutdownPostgresFast'.
+mkPostgresGargoyle :: FilePath -- ^ Path to `initdb`
+                   -> FilePath -- ^ Path to `postgres`
+                   -> (ProcessHandle -> IO ()) -- ^ Shutdown function
+                   -> Gargoyle ProcessHandle ByteString
+                   -- ^ The 'Gargoyle' returned provides to client code the connection
+                   -- string that can be used to connect to the PostgreSQL server
+mkPostgresGargoyle initdbPath postgresPath shutdownFun = Gargoyle
+  { _gargoyle_exec = "gargoyle-postgres-monitor"
+  , _gargoyle_init = initLocalPostgres initdbPath
+  , _gargoyle_start = startLocalPostgres postgresPath
+  , _gargoyle_stop = shutdownFun
+  , _gargoyle_getInfo = getLocalPostgresConnectionString
+  }
+
+-- | Create a new PostgreSQL database in a local folder. This is a low level function used to
+-- define the PostgreSQL 'Gargoyle'.
+initLocalPostgres :: FilePath -- ^ Path to PostgreSQL `initdb` executable
+                  -> FilePath -- ^ Path in which to initialize PostgreSQL Server
+                  -> IO ()
+initLocalPostgres binPath dbDir = do
+  (_, _, _, initdb) <- runInteractiveProcess binPath
+    [ "-D", dbDir
+    , "-U", "postgres"
+    , "--no-locale"
+    , "-E", "UTF8"
+    ] Nothing Nothing
+  ExitSuccess <- waitForProcess initdb
+  return ()
+
+-- | Produces the connection string for a local postgresql database. This is a low level function
+-- used to define the PostgreSQL 'Gargoyle'
+getLocalPostgresConnectionString :: FilePath -> IO ByteString
+getLocalPostgresConnectionString dbDir = do
+  absoluteDbDir <- makeAbsolute dbDir
+  return $ mconcat $
+    [ "postgresql://postgres@"
+    , (LBS.toStrict $ BS.replace "/" ("%2F" :: LBS.ByteString) $ T.encodeUtf8 $ T.pack absoluteDbDir)
+    , "/postgres"
+    ]
+
+-- | Start a postgres server that is assumed to be in the given folder. This is a low level function
+-- used to define the PostgreSQL 'Gargoyle'
+startLocalPostgres :: FilePath -- ^ Path to PostgreSQL `postgres` executable
+                   -> FilePath -- ^ Path where the server to start is located
+                   -> IO ProcessHandle -- ^ handle of the PostgreSQL server
+startLocalPostgres binPath dbDir = do
+  absoluteDbDir <- makeAbsolute dbDir
+  (_, _, err, postgres) <- runInteractiveProcess binPath
+    [ "-h", ""
+    , "-D", absoluteDbDir
+    , "-k", absoluteDbDir
+    ] Nothing Nothing
+  fix $ \loop -> do
+    l <- hGetLine err
+    let (tag, rest) = span (/= ':') l
+    when (tag /= "LOG") $ fail $ "startLocalPostgres: Unexpected output from postgres: " <> show l
+    when (rest /= ":  database system is ready to accept connections") loop
+  return postgres
+
+-- | Perform a "Smart Shutdown" of Postgres;
+-- see http://www.postgresql.org/docs/current/static/server-shutdown.html
+shutdownPostgresSmart :: ProcessHandle -- ^ handle of the PostgreSQL server
+                      -> IO ()
+shutdownPostgresSmart postgres = do
+  terminateProcess postgres
+  _ <- waitForProcess postgres
+  return ()
+
+-- | Perform a "Fast Shutdown" of Postgres;
+-- see http://www.postgresql.org/docs/current/static/server-shutdown.html
+shutdownPostgresFast :: ProcessHandle -- ^ handle of the PostgreSQL server
+                     -> IO ()
+shutdownPostgresFast postgres = do
+  withProcessHandle postgres $ \p -> do
+    case p of
+      ClosedHandle _ -> return ()
+      OpenHandle h -> signalProcess sigINT h
+  _ <- waitForProcess postgres
+  return ()
+
+-- | Run `psql` against a Gargoyle managed db.
+psqlLocal :: Gargoyle pid ByteString -- ^ 'Gargoyle' against which to run
+          -> FilePath -- ^ The path to `psql`
+          -> FilePath -- ^ The path where the managed daemon is expected
+          -> Maybe String
+          -- ^ Optionally provide stdin input instead of an inheriting current stdin.
+          -- It will have a newline and quit command appended to it.
+          -> IO ()
+psqlLocal g psqlPath dbPath minput = withGargoyle g dbPath $ \dbUri -> do
+  void $ installHandler keyboardSignal Ignore Nothing
+  let psqlProc = (proc psqlPath [ T.unpack $ T.decodeUtf8 dbUri ])
+        { std_in = case minput of
+            Nothing -> Inherit
+            Just _ -> CreatePipe
+        , std_out = Inherit
+        , std_err = Inherit
+        }
+  (mStdin, _, _, psql) <- createProcess psqlProc
+  case minput of
+    Nothing -> return ()
+    Just input -> hPutStrLn (fromJust mStdin) (input ++ "\n\\q")
+  ExitSuccess <- waitForProcess psql
+  return ()
diff --git a/tests/gargoyle-psql-test.hs b/tests/gargoyle-psql-test.hs
new file mode 100644
--- /dev/null
+++ b/tests/gargoyle-psql-test.hs
@@ -0,0 +1,20 @@
+module Main where
+
+import System.Directory
+import System.Exit
+import System.FilePath
+import System.Posix.Temp
+
+import Gargoyle
+import Gargoyle.PostgreSQL
+
+main :: IO ()
+main = do
+  let testPostgres = defaultPostgres
+        { _gargoyle_exec = "dist/build" </> "gargoyle-postgres-monitor/gargoyle-postgres-monitor"
+        }
+  --TODO make this exception safe
+  testPath <- mkdtemp "psql-test"
+  psqlLocal testPostgres "psql" (testPath </> "db") (Just "")
+  removeDirectoryRecursive testPath
+  exitSuccess
