diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -6,6 +6,8 @@
 Shh is a library to enable convinient shell-like programming in Haskell.
 It works well in scripts, and from GHCi, allowing you to use GHCi as a shell.
 
+It is also a wrapper tool around launching GHCi as a shell.
+
 It supports
 
  * Automatically defining a function for each executable on your `$PATH`
@@ -99,6 +101,20 @@
     ls &!> StdOut  Redirect stderr of `ls` to wherever stdout is going.
     StdOut <!& ls  Same as above
 
+## Globbing
+
+Currently Shh does not have any built in globbing support. Rather, it is
+currently suggested to use another library to do globbing. For example,
+using the [Glob](http://hackage.haskell.org/package/Glob) package, it is
+possible to do something like
+
+    wc =<< glob "*.md"
+
+Certainly more verbose than the Bash equivalent, however, also more explicit,
+which is probably a good thing. If this turns out to be too cumbersome, we
+might introduce a more succinct globbing feature, though it will always be
+explicit, and thus always more verbose than most other shells.
+
 ## Usage
 
 Enable Temlpate Haskell and load the environment
@@ -120,7 +136,31 @@
 `initInteractive` function. This sets the line buffering appropriately and
 ensures the terminal is in canonical mode.
 
+### Shh as a Shell
+
+There is a tool called `shh` which is a fairly small wrapper around launching
+GHCi which automatically loads your environment and allows you to have custom
+config when using GHCi as a shell.
+
+The `shh` binary will look in your `$SHH_DIR` (defaults to `$HOME/.shh`) for
+a `Shell.hs`, `init.ghci` and `wrapper` files. If these don't exist default
+ones will be created.
+
+The `Shell.hs` file should contain any top level definitions that you would
+like to be available in your Shell. By default it loads your environment.
+
+The `init.ghci` file is loaded by GHCi after your `.ghci` files. This lets
+you specify settings that you want to take effect when using GHCi as a shell.
+By default it sets a shell-like prompt.
+
+The `wrapper` file is an executable that is called with the command that is
+to be executed. By default it just calls `exec` with the arguments passed to
+it. The use-case for this is to be able to set up the environment for `shh`.
+You might, for example, wrap the execution in a `nix-shell`. Either way,
+it is up to you to make sure that the compiler, and packages you require are
+available, either globally, or provided by the `wrapper` script.
+
 ### Script Usage
 
-TODO: Fill this in once on Hackage.
+TODO: Fill this in once the user experience is better.
     
diff --git a/app/shh-app.hs b/app/shh-app.hs
new file mode 100644
--- /dev/null
+++ b/app/shh-app.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE LambdaCase #-}
+module Main where
+
+import Shh
+import System.IO
+import System.Environment
+import System.IO.Temp
+import System.Directory
+import Data.Hashable (hash)
+import Data.List.Split (splitOn)
+
+defaultShell = "\
+\{-# LANGUAGE TemplateHaskell #-}\n\
+\module Shell where\n\
+\import Shh\n\
+\$(loadEnv SearchPath)\n\
+\ "
+
+defaultInitGhci = "\
+\:seti -XNoOverloadedLists\n\
+\import Shh\n\
+\import Shh.Prompt\n\
+\:set prompt-function promptFormat \"\\n\\ESC[1;32m[%u@%h:%w]λ \\ESC[0m\"\n\
+\:set prompt-cont \"| \"\n\
+\ "
+
+
+defaultWrapper = "\
+\#! /usr/bin/env sh\n\
+\exec \"$@\"\n\
+\ "
+
+debug = putStrLn
+
+writeIfMissing :: FilePath -> String -> IO ()
+writeIfMissing fp s = do
+    doesFileExist fp >>= \case
+        True -> pure ()
+        False -> writeFile fp s
+
+main :: IO ()
+main = do
+    a <- getArgs
+    shhDir <- lookupEnv "SHH_DIR" >>= \case
+        Nothing -> lookupEnv "HOME" >>= \case
+            Nothing -> error "Please specify HOME or SHH_DIR environment variables"
+            Just h  -> pure $ h <> "/.shh"
+        Just s -> pure s
+
+    let
+        wrapped :: (Unit a, ExecArgs a) => a
+        wrapped = exe (shhDir <> "/wrapper")
+
+
+    debug $ "Shh home is: " <> shhDir
+
+    createDirectoryIfMissing False shhDir
+
+    withCurrentDirectory shhDir $ do
+        writeIfMissing "init.ghci" defaultInitGhci
+        writeIfMissing "wrapper" defaultWrapper
+        setPermissions "wrapper" $
+            setOwnerExecutable True $
+            setOwnerReadable True $
+            setOwnerWritable True $
+            emptyPermissions
+        writeIfMissing "Shell.hs" defaultShell
+
+    wrapped "ghci" "-ghci-script" (shhDir <> "/init.ghci") (shhDir <> "/Shell.hs")
+
diff --git a/shh.cabal b/shh.cabal
--- a/shh.cabal
+++ b/shh.cabal
@@ -1,5 +1,5 @@
 name:                shh
-version:             0.2.0.2
+version:             0.2.0.3
 synopsis:            Simple shell scripting from Haskell
 description:         Provides a shell scripting environment for Haskell. It
                      helps you all external binaries, and allows you to
@@ -9,7 +9,7 @@
 license-file:        LICENSE
 author:              Luke Clifton
 maintainer:          lukec@themk.net
-copyright:           (c) 2018 Luke Clifton
+copyright:           (c) 2018, 2019 Luke Clifton
 category:            System
 build-type:          Simple
 extra-source-files:  ChangeLog.md, README.md
@@ -37,6 +37,23 @@
   default-language:    Haskell2010
   ghc-options: -Wall
 
+executable shh
+  ghc-options: -threaded
+  default-language: Haskell2010
+  build-depends:
+    base >=4.9,
+    async,
+    hashable,
+    hashable,
+    temporary,
+    directory,
+    shh,
+    split
+  hs-source-dirs: app
+  main-is: shh-app.hs
+  build-tools:
+    ghc
+
 executable shh-example
   ghc-options: -threaded -with-rtsopts=-N
   default-language: Haskell2010
@@ -48,7 +65,6 @@
   main-is: Example.hs
   build-tools:
     coreutils,
-    vault,
     vim
   
 
diff --git a/src/Shh.hs b/src/Shh.hs
--- a/src/Shh.hs
+++ b/src/Shh.hs
@@ -48,6 +48,8 @@
     , catchCode
     -- | == Constructing Arguments
     , ExecArg(..)
+    , ExecArgs()
+    , Unit()
     -- | == Template Haskell helpers
     , ExecReference(..)
     , load
