diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+Copyright 2005-2006, Robert Dockins.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistribution of source code must retain the above copyright notice,
+this list of conditions and the following disclamer.
+
+- Redistribution in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclamer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR THE 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/Shellac-readline.cabal b/Shellac-readline.cabal
new file mode 100644
--- /dev/null
+++ b/Shellac-readline.cabal
@@ -0,0 +1,25 @@
+Name:           Shellac-readline
+Version:        0.9
+License:        BSD3
+License-File:   LICENSE
+Author:         Robert Dockins
+Maintainer:     robdockins AT fastmail DOT fm
+Category:       User Interfaces
+Stability:      Beta
+Synopsis:       Readline backend module for Shellac
+Description:
+   This package provides a Shellac backend based on the GNU readline
+   library.  This backend features all the line editing capabilities
+   provided by readline, as well as command completion and command
+   history features.
+Hs-Source-Dirs:
+   src
+Build-Depends:
+   base >= 1.0,
+   haskell98 >= 1.0,
+   readline >= 1.0,
+   Shellac >= 0.9
+Exposed-modules:
+   System.Console.Shell.Backend.Readline
+Extensions:
+   ForeignFunctionInterface
diff --git a/src/System/Console/Shell/Backend/Readline.hs b/src/System/Console/Shell/Backend/Readline.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Console/Shell/Backend/Readline.hs
@@ -0,0 +1,132 @@
+{-
+ - 
+ -  Copyright 2005-2007, Robert Dockins.
+ -  
+ -}
+
+{- | This module implements a Shellac backend based on the GNU readline
+     and GNU history modules.  For readline, we use the bindings
+     from the standard library.  For history, we import directily using
+     FFI.  This Shellac backend supports command completion, history buffer
+     and all the line editing and character binding features of GNU readline.
+
+     Beware that while the code for this Shellac binding is licensed under a BSD3
+     license, GNU readline itself is licensed under the GPL.  This means that your
+     project needs to be GPL compatible for this Shellac backend to be useful to you.
+-}
+
+
+module System.Console.Shell.Backend.Readline
+( readlineBackend
+) where
+
+import System.IO            ( stdin, stdout, stderr, hFlush, hPutStr, hPutStrLn, hGetChar
+                            , hSetBuffering, hGetBuffering
+                            , BufferMode(..)
+                            )
+import Foreign.Ptr          ( Ptr )
+import Foreign.C            ( CInt, CString, withCString )
+import Foreign.C.Error      ( Errno, eOK, errnoToIOError )
+import Foreign.Storable     ( peek )
+
+import qualified Control.Exception as Ex
+import qualified System.Console.Readline as RL
+
+import System.Console.Shell.Backend 
+
+readlineBackend :: ShellBackend ()
+readlineBackend = ShBackend
+  { initBackend                      = doReadlineInit
+  , shutdownBackend                  = \_ -> doReadlineShutdown
+  , outputString                     = \_ -> readlineOutput
+  , flushOutput                      = \_ -> hFlush stdout
+  , getInput                         = \_ -> RL.readline
+  , getSingleChar                    = \_ -> readlineGetSingleChar
+  , addHistory                       = \_ -> RL.addHistory
+  , getWordBreakChars                = \_ -> RL.getBasicWordBreakCharacters
+  , setWordBreakChars                = \_ -> RL.setBasicWordBreakCharacters
+  , onCancel                         = \_ -> hPutStrLn stdout "canceled..."
+  , setAttemptedCompletionFunction   = \_ -> readlineCompletionFunction
+  , setDefaultCompletionFunction     = \_ -> RL.setCompletionEntryFunction
+  , completeFilename                 = \_ -> RL.filenameCompletionFunction
+  , completeUsername                 = \_ -> RL.usernameCompletionFunction
+  , clearHistoryState                = \_ -> doClearHistoryState
+  , setMaxHistoryEntries             = \_ -> doSetMaxHistoryEntries
+  , getMaxHistoryEntries             = \_ -> doGetMaxHistoryEntries
+  , readHistory                      = \_ -> doReadHistory
+  , writeHistory                     = \_ -> doWriteHistory
+  }
+
+
+readlineCompletionFunction :: CompletionFunction -> IO ()
+readlineCompletionFunction f = RL.setAttemptedCompletionFunction (Just complete)
+
+ where complete word begin end = do
+          buffer <- RL.getLineBuffer
+          let before = take begin buffer
+          let after  = drop end buffer
+
+          f (before,word,after)
+
+
+readlineGetSingleChar :: String -> IO (Maybe Char)
+readlineGetSingleChar prompt = do
+   hPutStr stdout prompt
+   hFlush stdout
+   Ex.bracket (hGetBuffering stdin) (hSetBuffering stdin) $ \_ -> do
+      hSetBuffering stdin NoBuffering
+      c <- hGetChar stdin
+      hPutStrLn stdout ""
+      return (Just c)
+
+foreign import ccall "readline/history.h clear_history" clear_history :: IO ()
+foreign import ccall "readline/history.h stifle_history" stifle_history :: CInt -> IO ()
+foreign import ccall "readline/history.h read_history" read_history :: CString -> IO Errno
+foreign import ccall "readline/history.h write_history" write_history :: CString -> IO Errno
+foreign import ccall "readline/history.h &history_max_entries" history_max_entries :: Ptr CInt
+foreign import ccall "readline/history.h using_history" using_history :: IO ()
+
+doReadlineInit :: IO ()
+doReadlineInit = do
+   using_history
+   return ()
+
+doReadlineShutdown :: IO ()
+doReadlineShutdown = do
+   return ()
+
+doClearHistoryState :: IO ()
+doClearHistoryState = clear_history
+
+doSetMaxHistoryEntries :: Int -> IO ()
+doSetMaxHistoryEntries m = stifle_history (fromIntegral m)
+
+doGetMaxHistoryEntries :: IO Int
+doGetMaxHistoryEntries = peek history_max_entries >>= return . fromIntegral
+
+doReadHistory :: FilePath -> IO ()
+doReadHistory path = do
+  err <- withCString path read_history
+  if err == eOK
+     then return ()
+     else ioError $ errnoToIOError 
+              "System.Console.Shell.Backend.Readline.doReadHistory"
+              err
+              Nothing
+              (Just path)
+
+doWriteHistory :: FilePath -> IO ()
+doWriteHistory path = do
+  err <- withCString path write_history
+  if err == eOK
+     then return ()
+     else ioError $ errnoToIOError
+              "System.Console.Shell.Backend.Readline.doWriteHistory"
+              err
+              Nothing
+              (Just path)
+
+readlineOutput :: BackendOutput -> IO ()
+readlineOutput (RegularOutput str)  = hPutStr stdout str
+readlineOutput (InfoOutput str)     = hPutStr stdout str
+readlineOutput (ErrorOutput str)    = hPutStr stderr str
