diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for wild-bind-x11
+
+## 0.1.0.0  -- 2016-09-22
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, Toshio Ito
+
+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 Toshio Ito nor the names of other
+      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
+OWNER 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+# wild-bind
+
+WildBind is a dynamic and programmable key binding framework. See https://github.com/debug-ito/wild-bind for WildBind in general.
+
+## Architecture and Terminology
+
+WildBind consists of `FrontEnd` and `Binding`.
+
+                     +-------------------+
+    (user) --input-> |   desktop env.    |---[FrontEnd]---[Binding]
+                     |                   |                    |
+                     | (front-end state) |             (back-end state)
+                     +-------------------+
+
+- A `FrontEnd` interfaces with a desktop environment. It reads input from the user and the state of the desktop environment. The state is called "front-end state". `FrontEnd` passes those two kinds of data to `Binding`.
+- A `Binding` binds actions to input symbols. Optionally it has its own state, which is called "back-end state".
+
+
+## wild-bind Packages
+
+- wild-bind: WildBind core data types and functions. This package defines `FrontEnd`, `Binding` and other common types. Although WildBind is mainly targeted to number pads, its core is independent of any input types or desktop environments.
+- wild-bind-x11: A `FrontEnd` implementation for X11 desktop environments.
+- wild-bind-indicator: A GUI that describes current `Binding` to the user.
+- wild-bind-task-x11: A bundle package that combines all packages above. End users should use this package first.
+
+
+## Author
+
+Toshio Ito <debug.ito at gmail.com>
+
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/src/WildBind.hs b/src/WildBind.hs
new file mode 100644
--- /dev/null
+++ b/src/WildBind.hs
@@ -0,0 +1,32 @@
+-- |
+-- Module: WildBind
+-- Description: WildBind main module
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- 
+module WildBind
+       ( module WildBind.Binding,
+         -- | Defines 'Binding' and many functions to build it.
+         
+         module WildBind.FrontEnd,
+         -- | Defines 'FrontEnd', an interface between 'Binding' and a
+         -- desktop environment.
+         
+         module WildBind.Exec,
+         -- | Defines functions to combine 'Binding' and 'FrontEnd'
+         -- into an executable action. You can customize its behavior
+         -- via 'Option'.
+         
+         module WildBind.Description,
+         -- | Defines 'ActionDescription'.
+         
+         module WildBind.Input.NumPad
+         -- | Defines input symbol types for number pad keys.
+       ) where
+
+
+import WildBind.Description
+import WildBind.Binding
+import WildBind.FrontEnd
+import WildBind.Exec
+import WildBind.Input.NumPad
diff --git a/src/WildBind/Binding.hs b/src/WildBind/Binding.hs
new file mode 100644
--- /dev/null
+++ b/src/WildBind/Binding.hs
@@ -0,0 +1,326 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+-- |
+-- Module: WildBind.Binding
+-- Description: Functions to build Binding
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- This module exports functions to build and manipulate 'Binding', an
+-- object binding input symbols to actions.
+-- 
+module WildBind.Binding
+       ( -- * Types
+         Action(Action,actDescription,actDo),
+         Binding,
+         Binding',
+         
+         -- * Construction
+
+         -- | Functions to create fundamental 'Binding's.
+         --
+         -- To create complex 'Binding's, use <#Condition Condition> functions
+         -- described below and 'mappend' them together.
+         
+         noBinding,
+         Binder,
+         binds,
+         binds',
+         on,
+         run,
+         as,
+         binding,
+         binding',
+         
+         -- * Condition
+         
+         -- | #Condition# With these functions, you can create
+         -- 'Binding's that behave differently for different front-end
+         -- and/or back-end states.
+         --
+         -- If you call the condition functions multiple times, the
+         -- conditions are combined with AND logic.
+         ifFront,
+         ifBack,
+         ifBoth,
+         whenFront,
+         whenBack,
+         whenBoth,
+         -- * Conversion
+         advice,
+         before,
+         after,
+         startFrom,
+         extend,
+         convFront,
+         convInput,
+         convBack,
+         -- * Execution
+         boundAction,
+         boundAction',
+         boundActions,
+         boundActions',
+         boundInputs,
+         boundInputs'
+       ) where
+
+import Control.Applicative (Applicative, (<*), (*>))
+import Control.Monad.Trans.State (StateT, runStateT)
+import Control.Monad.Trans.Writer (Writer, tell, execWriter, mapWriter)
+import qualified Data.Map as M
+import Data.Monoid (Monoid(..), Endo(Endo, appEndo))
+
+import WildBind.Description (ActionDescription)
+
+-- | Action done by WildBind
+data Action m a =
+  Action
+  { actDescription :: ActionDescription, -- ^ Human-readable description of the action.
+    actDo :: m a -- ^ The actual job.
+  }
+
+instance Show (Action m a) where
+  show a = "Action " ++ show (actDescription a)
+
+instance Functor m => Functor (Action m) where
+  fmap f a = a { actDo = fmap f (actDo a) }
+
+-- | Make an 'Action' that runs the given monadic action before the
+-- original 'Action'.
+before :: (Applicative m)
+       => m b -- ^ the monadic action prepended
+       -> Action m a -- ^ the original 'Action'.
+       -> Action m a
+before hook act = act { actDo = hook *> actDo act }
+
+-- | Make an 'Action' that runs the given monadic action after the
+-- original 'Action'.
+after :: (Applicative m)
+      => m b -- ^ the monadic action appended.
+      -> Action m a -- ^ the original 'Action'.
+      -> Action m a
+after hook act = act { actDo = actDo act <* hook }
+
+-- | WildBind back-end binding with both explicit and implicit
+-- states. @bs@ is the explicit back-end state, @fs@ is the front-end
+-- state, and @i@ is the input type.
+--
+-- You can make the explicit state @bs@ implicit by 'startFrom'
+-- function.
+newtype Binding' bs fs i =
+  Binding'
+  { unBinding' :: bs -> fs -> M.Map i (Action IO (Binding' bs fs i, bs))
+  }
+
+-- | WildBind back-end binding between inputs and actions. @s@ is the
+-- front-end state type, and @i@ is the input type.
+type Binding s i = Binding' () s i
+
+-- | 'mempty' returns a 'Binding' where no binding is
+-- defined. 'mappend' combines two 'Binding's while preserving their
+-- individual implicit states. The right-hand 'Binding' has precedence
+-- over the left-hand one. That is, if the two 'Binding's both have a
+-- binding to the same key in the same front-end and back-end state,
+-- the binding from the right-hand one is used.
+instance Ord i => Monoid (Binding' bs fs i) where
+  mempty = noBinding
+  mappend abind bbind = Binding' $ \bs fs ->
+    let amap = mapResult (`mappend` bbind) id $ unBinding' abind bs fs
+        bmap = mapResult (abind `mappend`) id $ unBinding' bbind bs fs
+    in M.unionWith (\_ b -> b) amap bmap
+
+-- | A 'Binding'' with no bindings. It's the same as 'mempty', except
+-- 'noBinding' requires no context.
+noBinding :: Binding' bs fs i
+noBinding = Binding' $ \_ _ -> M.empty
+
+-- | Get the 'Action' bound to the specified state @s@ and input @i@.
+boundAction :: (Ord i) => Binding s i -> s -> i -> Maybe (Action IO (Binding s i))
+boundAction b state input = (fmap . fmap) fst $ boundAction' b () state input
+
+-- | Get the 'Action' bound to the specified back-end state @bs@,
+-- front-end state @fs@ and input @i@
+boundAction' :: (Ord i) => Binding' bs fs i -> bs -> fs -> i -> Maybe (Action IO (Binding' bs fs i, bs))
+boundAction' b bs fs input = M.lookup input $ unBinding' b bs fs
+
+-- | Get the list of all bound inputs @i@ and their corresponding
+-- actions for the specified front-end state @s@.
+boundActions :: Binding s i -> s -> [(i, Action IO (Binding s i))]
+boundActions b state = fmap (\(i, act) -> (i, fmap fst act)) $ boundActions' b () state
+
+-- | Get the list of all bound inputs @i@ and their corresponding
+-- actions for the specified back-end state @bs@ and front-end state
+-- @fs@.
+boundActions' :: Binding' bs fs i -> bs -> fs -> [(i, Action IO (Binding' bs fs i, bs))]
+boundActions' b bs fs = M.toList $ unBinding' b bs fs
+
+-- | Get the list of all bound inputs @i@ for the specified front-end
+-- state @s@.
+boundInputs :: Binding s i -> s -> [i]
+boundInputs b s = fmap fst $ boundActions b s
+
+-- | Get the list of all bound inputs @i@ for the specified front-end
+-- state @fs@ and the back-end state @bs@.
+boundInputs' :: Binding' bs fs i -> bs -> fs -> [i]
+boundInputs' b bs fs = fmap fst $ boundActions' b bs fs
+
+
+-- | A monad to construct 'Binding''. @i@ is the input symbol, and @v@
+-- is supposed to be the 'Action' bound to @i@.
+newtype Binder i v a = Binder { unBinder :: Writer (Endo [(i, v)]) a }
+                       deriving (Monad,Applicative,Functor)
+
+runBinder :: Binder i v a -> [(i, v)] -> [(i, v)]
+runBinder = appEndo . execWriter . unBinder
+
+-- | Build a 'Binding' with no explicit or implicit state. The bound
+-- actions are activated regardless of the back-end or front-end
+-- state.
+--
+-- If different actions are bound to the same input, the latter action
+-- wins.
+--
+-- Result of action (@r@) is discarded.
+binds :: Ord i => Binder i (Action IO r) a -> Binding' bs fs i
+binds = binding . flip runBinder []
+
+-- | Build a 'Binding'' with an explicit state (but no implicit
+-- state). The bound actions are activated regardless of the back-end
+-- or front-end state.
+binds' :: Ord i => Binder i (Action (StateT bs IO) r) a -> Binding' bs fs i
+binds' = binding' . flip runBinder []
+
+-- | Create a 'Binder' that binds the action @v@ to the input @i@.
+on :: i -> v -> Binder i v ()
+on i v = Binder $ tell $ Endo ((i,v) :)
+
+-- | Transform the given action @m a@ into an 'Action' and apply the
+-- continuation to it. It discards the result of action (type
+-- @a@). Usually used as an operator.
+run :: Functor m => (Action m () -> b) -> m a -> b
+run cont raw_act = cont $ Action { actDescription = "", actDo = fmap (const ()) raw_act }
+
+infixl 2 `run`
+
+-- | Transform the given continuation so that the 'ActionDescription'
+-- is set to the 'Action' passed to the continuation. Usually used as
+-- an operator.
+as :: (Action m a -> b) -> ActionDescription -> Action m a -> b
+as cont desc act = cont $ act { actDescription = desc }
+
+infixl 2 `as`
+
+-- | Transform the actions in the given 'Binder'.
+advice :: (v -> v') -> Binder i v a -> Binder i v' a
+advice f = Binder . mapWriter f_writer . unBinder where
+  f_writer (a, e) = (a, f_endo e)
+  f_endo (Endo prepender) = Endo ((map f_pair $ prepender []) ++)
+  f_pair (i, v) = (i, f v)
+
+
+-- | Non-monadic version of 'binds'.
+binding :: Ord i => [(i, Action IO r)] -> Binding' bs fs i
+binding blist = impl where
+  impl = Binding' $ \bs _ -> (fmap . fmap) (const (impl, bs)) $ M.fromList blist
+
+-- | Create a binding that behaves differently for different front-end
+-- states @fs@.
+ifFront :: (fs -> Bool) -- ^ The predicate
+        -> Binding' bs fs i -- ^ Enabled if the predicate is 'True'
+        -> Binding' bs fs i -- ^ Enabled if the predicate is 'False'
+        -> Binding' bs fs i
+ifFront p = ifBoth $ \_ fs -> p fs
+
+-- | Create a binding that behaves differently for different back-end
+-- states @bs@.
+ifBack :: (bs -> Bool) -- ^ The predicate
+       -> Binding' bs fs i -- ^ Enabled if the predicate is 'True'
+       -> Binding' bs fs i -- ^ Enabled if the predicate is 'False'
+       -> Binding' bs fs i
+ifBack p = ifBoth $ \bs _ -> p bs
+
+-- | Create a binding that behaves differently for different front-end
+-- and back-end states, @fs@ and @bs@.
+ifBoth :: (bs -> fs -> Bool) -- ^ The predicate
+       -> Binding' bs fs i -- ^ Enabled if the predicate is 'True'
+       -> Binding' bs fs i -- ^ Enabled if the predicate is 'False'
+       -> Binding' bs fs i
+ifBoth p thenb elseb = Binding' $ \bs fs ->
+  if p bs fs
+  then mapResult (\nextb -> ifBoth p nextb elseb) id $ unBinding' thenb bs fs
+  else mapResult (\nextb -> ifBoth p thenb nextb) id $ unBinding' elseb bs fs
+
+-- | Add a condition on the front-end state to 'Binding'.
+whenFront :: (fs -> Bool) -- ^ The predicate.
+          -> Binding' bs fs i -- ^ Enabled if the predicate is 'True'
+          -> Binding' bs fs i
+whenFront p = whenBoth $ \_ fs -> p fs
+
+-- | Add a condition on the back-end state to 'Binding'.
+whenBack :: (bs -> Bool) -- ^ The predicate.
+         -> Binding' bs fs i -- ^ Enabled if the predicate is 'True'
+         -> Binding' bs fs i
+whenBack p = whenBoth $ \bs _ -> p bs
+
+-- | Add a condition on the back-end and front-end states to
+-- 'Binding'.
+whenBoth :: (bs -> fs -> Bool) -- ^ The predicate.
+         -> Binding' bs fs i -- ^ Enabled if the predicate is 'True'.
+         -> Binding' bs fs i
+whenBoth p b = ifBoth p b noBinding
+
+mapResult :: Functor m => (a -> a') -> (b -> b') -> M.Map i (Action m (a, b)) -> M.Map i (Action m (a',b'))
+mapResult amapper bmapper = (fmap . fmap) (\(a, b) -> (amapper a, bmapper b))
+
+-- | Contramap the front-end state.
+convFront :: (fs -> fs') -> Binding' bs fs' i -> Binding' bs fs i
+convFront cmapper orig_bind = Binding' $ \bs fs ->
+  mapResult (convFront cmapper) id $ unBinding' orig_bind bs (cmapper fs)
+
+-- | Map the front-end input.
+convInput :: Ord i' => (i -> i') -> Binding' bs fs i -> Binding' bs fs i'
+convInput mapper orig_bind = Binding' $ \bs fs ->
+  mapResult (convInput mapper) id $ M.mapKeys mapper $ unBinding' orig_bind bs fs
+
+-- | Convert the back-end state. Intuitively, it converts a small
+-- state type @bs@ into a bigger state type @bs'@, which includes
+-- @bs@.
+--
+-- For example, if you have a 'Control.Lens.Lens'' @l@, you can do
+--
+-- > convBack (set l) (view l) b
+convBack :: (bs -> bs' -> bs') -- ^ A setter. It's supposed to set
+                               -- @bs@ into the original @bs'@ and
+                               -- return the result.
+         -> (bs' -> bs) -- ^ A getter. It's supposed to extract @bs@
+                        -- from @bs'@.
+         -> Binding' bs fs i
+         -> Binding' bs' fs i
+convBack setter getter orig_bind = Binding' $ \bs' fs ->
+  mapResult (convBack setter getter) (\bs -> setter bs bs') $ unBinding' orig_bind (getter bs') fs
+
+-- | Convert 'Binding'' to 'Binding' by hiding the explicit state
+-- @bs@.
+startFrom :: bs -- ^ Initial state
+          -> Binding' bs fs i -- ^ Binding' with explicit state
+          -> Binding fs i -- ^ Binding containing the state inside
+startFrom init_state b' = Binding' $ \() front_state ->
+  (fmap . fmap) toB $ unBinding' b' init_state front_state
+  where
+    toB (next_b', next_state) = (startFrom next_state next_b', ())
+
+-- | Extend 'Binding' to 'Binding''. In the result 'Binding'', the
+-- explicit back-end state is just ignored and unmodified.
+extend :: Binding fs i -> Binding' bs fs i
+extend = convBack (const id) (const ())
+
+-- | Non-monadic version of 'binds''.
+binding' :: Ord i => [(i, Action (StateT bs IO) r)] -> Binding' bs fs i
+binding' blists = impl where
+  impl = Binding' $ \bs _ -> fmap (runStatefulAction impl bs) $ M.fromList $ blists
+
+runStatefulAction :: Binding' bs fs i -> bs -> Action (StateT bs IO) r -> Action IO (Binding' bs fs i, bs)
+runStatefulAction next_b' cur_bs state_action =
+  state_action { actDo = recursive_io }
+  where
+  recursive_io = do
+    (_, next_bs) <- runStateT (actDo state_action) cur_bs
+    return (next_b', next_bs)
diff --git a/src/WildBind/Description.hs b/src/WildBind/Description.hs
new file mode 100644
--- /dev/null
+++ b/src/WildBind/Description.hs
@@ -0,0 +1,19 @@
+-- |
+-- Module: WildBind.Description
+-- Description: Types about ActionDescription
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+module WildBind.Description
+       ( ActionDescription,
+         Describable(..)
+       ) where
+
+import Data.Text (Text)
+
+-- | Human-readable description of an action. 'ActionDescription' is
+-- used to describe the current binding to the user.
+type ActionDescription = Text
+
+-- | Class for something describable.
+class Describable d where
+  describe :: d -> ActionDescription
diff --git a/src/WildBind/Exec.hs b/src/WildBind/Exec.hs
new file mode 100644
--- /dev/null
+++ b/src/WildBind/Exec.hs
@@ -0,0 +1,133 @@
+-- |
+-- Module: WildBind.Exec
+-- Description: Functions to create executable actions.
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+-- 
+module WildBind.Exec
+       ( -- * Functions to build executable action
+         wildBind,
+         wildBind',
+         -- * Option for executable
+         Option,
+         defOption,
+         -- ** Accessor functions for 'Option'
+         optBindingHook,
+         optCatch
+       ) where
+
+import Control.Applicative ((<$>))
+import Control.Exception (SomeException, catch)
+import Control.Monad.IO.Class (liftIO)
+import Control.Monad.Trans.Class (lift)
+import qualified Control.Monad.Trans.Reader as Reader
+import qualified Control.Monad.Trans.State as State
+import Data.List ((\\))
+import System.IO (hPutStrLn, stderr)
+
+import WildBind.Description (ActionDescription)
+import WildBind.FrontEnd
+  ( FrontEvent(FEChange,FEInput),
+    FrontEnd(frontSetGrab, frontUnsetGrab, frontNextEvent)
+  )
+import WildBind.Binding
+  ( Action(actDo, actDescription),
+    Binding,
+    boundAction,
+    boundInputs,
+    boundActions
+  )
+
+type GrabSet i = [i]
+
+updateGrab :: (Eq i) => FrontEnd s i -> GrabSet i -> GrabSet i -> IO ()
+updateGrab f before after = do
+  mapM_ (frontUnsetGrab f) (before \\ after)
+  mapM_ (frontSetGrab f) (after \\ before)
+
+-- | Combines the 'FrontEnd' and the 'Binding' and returns the executable.
+wildBind :: (Ord i) => Binding s i -> FrontEnd s i -> IO ()
+wildBind = wildBind' defOption
+
+-- | Build the executable with 'Option'.
+wildBind' :: (Ord i) => Option s i -> Binding s i -> FrontEnd s i -> IO ()
+wildBind' opt binding front =
+  flip Reader.runReaderT opt $ flip State.evalStateT (binding, Nothing) $ wildBindInContext front
+
+-- | WildBind configuration options.
+--
+-- You can get the default value of 'Option' by 'defOption' funcion,
+-- and modify its members via accessor functions listed below.
+data Option s i =
+  Option { optBindingHook :: [(i, ActionDescription)] -> IO (),
+           -- ^ An action executed when current binding may be
+           -- changed. Default: do nothing.
+
+           optCatch :: s -> i -> SomeException -> IO ()
+           -- ^ the handler for exceptions thrown from bound
+           -- actions. Default: just print the 'SomeException' to
+           -- 'stderr' and ignore it.
+         }
+
+defOption :: Option s i
+defOption = Option { optBindingHook = const $ return (),
+                     optCatch = \_ _ exception -> hPutStrLn stderr ("Exception from WildBind action: " ++ show exception)
+                   }
+
+-- | Internal state. fst is the current Binding, snd is the current front-end state.
+type WBState s i = (Binding s i, Maybe s)
+
+-- | A monad keeping WildBind context.
+type WBContext s i = State.StateT (WBState s i) (Reader.ReaderT (Option s i) IO)
+
+askOption :: WBContext s i (Option s i)
+askOption = lift $ Reader.ask
+
+boundDescriptions :: Binding s i -> s -> [(i, ActionDescription)]
+boundDescriptions b s = fmap (\(i, act) -> (i, actDescription act)) $ boundActions b s
+
+updateWBState :: (Eq i) => FrontEnd s i -> Binding s i -> s -> WBContext s i ()
+updateWBState front after_binding after_state = do
+  (before_binding, before_mstate) <- State.get
+  let before_grabset = maybe [] (boundInputs before_binding) before_mstate
+  State.put $ (after_binding, Just after_state)
+  liftIO $ updateGrab front before_grabset (boundInputs after_binding after_state)
+  hook <- optBindingHook <$> askOption
+  liftIO $ hook $ boundDescriptions after_binding after_state
+
+updateFrontState :: (Eq i) => FrontEnd s i -> s -> WBContext s i ()
+updateFrontState front after_state = do
+  (cur_binding, _) <- State.get
+  updateWBState front cur_binding after_state
+
+updateBinding :: (Eq i) => FrontEnd s i -> Binding s i -> WBContext s i ()
+updateBinding front after_binding = do
+  (_, mstate) <- State.get
+  case mstate of
+    Nothing -> return ()
+    Just state -> updateWBState front after_binding state
+
+wildBindInContext :: (Ord i) => FrontEnd s i -> WBContext s i ()
+wildBindInContext front = impl where
+  impl = do
+    event <- liftIO $ frontNextEvent front
+    case event of
+      FEChange state ->
+        updateFrontState front state
+      FEInput input -> do
+        (cur_binding, mcur_state) <- State.get
+        case stateAndAction cur_binding mcur_state input of
+          Nothing -> return ()
+          Just (cur_state, action) -> do
+            handler <- getExceptionHandler cur_binding cur_state input
+            next_binding <- liftIO $ actDo action `catch` handler
+            updateBinding front next_binding
+    wildBindInContext front
+  stateAndAction binding mstate input = do
+    state <- mstate
+    action <- boundAction binding state input
+    return (state, action)
+  getExceptionHandler binding state input = do
+    opt_catch <- optCatch <$> askOption
+    return $ \e -> do
+      opt_catch state input e
+      return binding
diff --git a/src/WildBind/FrontEnd.hs b/src/WildBind/FrontEnd.hs
new file mode 100644
--- /dev/null
+++ b/src/WildBind/FrontEnd.hs
@@ -0,0 +1,34 @@
+-- |
+-- Module: WildBind.FrontEnd
+-- Description: Data types and type classes about front-ends.
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- Data types and type classes about front-ends.
+-- 
+-- You have to look at this module if you want to create a front-end
+-- implementation.
+module WildBind.FrontEnd
+       ( FrontEvent(..),
+         FrontEnd(..)
+       ) where
+
+import WildBind.Description (ActionDescription)
+
+-- | Event from the front-end. @s@ is the state of the front-end. @i@ is the input.
+data FrontEvent s i = FEInput i -- ^ An event that a new input is made.
+                    | FEChange s  -- ^ An event that the front-end state is changed.
+                    deriving (Show)
+
+-- | Interface to the front-end. @s@ is the state of the front-end,
+-- @i@ is the input.
+data FrontEnd s i =
+  FrontEnd
+  { frontDefaultDescription :: i -> ActionDescription,
+    -- ^ Default 'ActionDescription' for inputs
+    frontSetGrab :: i -> IO (),
+    -- ^ Action to grab (or capture) the specified input symbol on the device. 
+    frontUnsetGrab :: i -> IO (),
+    -- ^ Action to release the grab for the input symbol.
+    frontNextEvent :: IO (FrontEvent s i)
+    -- ^ Action to retrieve the next event. It should block if no event is queued.
+  }
diff --git a/src/WildBind/Input/NumPad.hs b/src/WildBind/Input/NumPad.hs
new file mode 100644
--- /dev/null
+++ b/src/WildBind/Input/NumPad.hs
@@ -0,0 +1,94 @@
+-- |
+-- Module: WildBind.Input.NumPad
+-- Description: Types about number pads
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- Input types for number pad keys.
+module WildBind.Input.NumPad
+       ( -- * NumLock disabled
+         NumPadUnlocked(..),
+         -- * NumLock enabled
+         NumPadLocked(..),
+       ) where
+
+import WildBind.Description (Describable(describe))
+
+-- | Number pad key input with NumLock disabled.
+data NumPadUnlocked
+  = NumInsert
+  | NumEnd
+  | NumDown
+  | NumPageDown
+  | NumLeft
+  | NumCenter
+  | NumRight
+  | NumHome
+  | NumUp
+  | NumPageUp
+  | NumDivide
+  | NumMulti
+  | NumMinus
+  | NumPlus
+  | NumEnter
+  | NumDelete
+  deriving (Eq,Ord,Show,Bounded,Enum)
+
+instance Describable NumPadUnlocked where
+  describe input = case input of
+    NumHome -> "Home"
+    NumUp -> "↑"
+    NumPageUp -> "PageUp"
+    NumLeft -> "←"
+    NumCenter -> ""
+    NumRight -> "→"
+    NumEnd -> "End"
+    NumDown -> "↓"
+    NumPageDown -> "PageDown"
+    NumDivide -> "/"
+    NumMulti -> "*"
+    NumMinus -> "-"
+    NumPlus -> "+"
+    NumEnter -> "Enter"
+    NumInsert -> "Insert"
+    NumDelete -> "Delete"
+
+
+-- | Number pad key input with NumLock enabled.
+data NumPadLocked
+  = NumL0
+  | NumL1
+  | NumL2
+  | NumL3
+  | NumL4
+  | NumL5
+  | NumL6
+  | NumL7
+  | NumL8
+  | NumL9
+  | NumLDivide
+  | NumLMulti
+  | NumLMinus
+  | NumLPlus
+  | NumLEnter
+  | NumLPeriod
+  deriving (Eq,Ord,Show,Bounded,Enum)
+
+instance Describable NumPadLocked where
+  describe input = case input of
+    NumL0 -> "0"
+    NumL1 -> "1"
+    NumL2 -> "2"
+    NumL3 -> "3"
+    NumL4 -> "4"
+    NumL5 -> "5"
+    NumL6 -> "6"
+    NumL7 -> "7"
+    NumL8 -> "8"
+    NumL9 -> "9"
+    NumLDivide -> "/"
+    NumLMulti -> "*"
+    NumLMinus -> "-"
+    NumLPlus -> "+"
+    NumLEnter -> "Enter"
+    NumLPeriod -> "."
+
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/test/WildBind/BindingSpec.hs b/test/WildBind/BindingSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/WildBind/BindingSpec.hs
@@ -0,0 +1,650 @@
+{-# LANGUAGE RankNTypes #-}
+module WildBind.BindingSpec (main, spec) where
+
+import Control.Applicative ((<$>), (<*>), pure)
+import Control.Monad (void, join)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import Control.Monad.Trans.Class (lift)
+import qualified Control.Monad.Trans.State as State
+import Data.Maybe (isNothing, fromJust)
+import Data.Monoid (mempty, (<>))
+import Data.IORef (IORef, modifyIORef, newIORef, readIORef, writeIORef)
+import qualified Lens.Micro as Lens
+import Test.Hspec
+import Test.QuickCheck (Gen, Arbitrary(arbitrary), property, listOf, sample')
+
+import qualified WildBind.Binding as WB
+import WildBind.ForTest (SampleInput(..), SampleState(..), SampleBackState(..))
+
+main :: IO ()
+main = hspec spec
+
+data BiggerSampleBackState = BSB { _lSB :: SampleBackState, _rSB :: SampleBackState }
+                           deriving (Show, Eq, Ord)
+
+lSB :: Lens.Lens' BiggerSampleBackState SampleBackState
+lSB = Lens.lens _lSB (\bsb sb -> bsb { _lSB = sb })
+
+rSB :: Lens.Lens' BiggerSampleBackState SampleBackState
+rSB = Lens.lens _rSB (\bsb sb -> bsb { _rSB = sb })
+
+-- 'view' is since microlens-0.3.5.0
+view :: Lens.Lens' s a -> s -> a
+view l s = s Lens.^. l
+
+newStrRef :: MonadIO m => m (IORef String)
+newStrRef = liftIO $ newIORef []
+
+withStrRef :: MonadIO m => (IORef String -> (String -> m ()) -> m ()) -> m ()
+withStrRef action = do
+  out <- newStrRef
+  let checkOut exp_str = liftIO $ readIORef out `shouldReturn` exp_str
+  action out checkOut
+
+outOn :: MonadIO m => IORef [a] -> i -> a -> (i, WB.Action m ())
+outOn out_ref input out_elem = (input, WB.Action "" $ liftIO $ modifyIORef out_ref (++ [out_elem]))
+
+outOnS :: MonadIO m => IORef [a] -> i -> a -> (s -> s) -> (i, WB.Action (State.StateT s m) ())
+outOnS out_ref input out_elem modifier = (,) input $ WB.Action "" $ do
+  State.modify modifier
+  liftIO $ modifyIORef out_ref (++ [out_elem])
+
+genStatelessBinding :: Arbitrary a => IORef [a] -> Gen (WB.Binding s SampleInput)
+genStatelessBinding out_list =
+  WB.binding <$> (listOf $ (,) <$> arbitrary <*> (WB.Action "" <$> outputRandomElem))
+  where
+    outputRandomElem = do
+      out_elem <- arbitrary
+      return $ modifyIORef out_list (out_elem :)
+  
+generate :: Gen a -> IO a
+generate = fmap head . sample'
+
+inputAll :: Ord i => WB.Binding s i -> s -> [i] -> IO (WB.Binding s i)
+inputAll b _ [] = return b
+inputAll binding state (i:rest) = case WB.boundAction binding state i of
+  Nothing -> inputAll binding state rest
+  Just act -> join $ inputAll <$> WB.actDo act <*> return state <*> return rest
+
+execAll :: Ord i => s -> [i] -> State.StateT (WB.Binding s i) IO ()
+execAll state inputs = do
+  b <- State.get
+  next_b <- liftIO $ inputAll b state inputs
+  State.put next_b
+
+execAll' :: Ord i => [i] -> State.StateT (WB.Binding SampleState i) IO ()
+execAll' = execAll (SS "")
+
+mempty_stateless :: WB.Binding SampleState SampleInput
+mempty_stateless = mempty
+
+checkMappend :: (WB.Binding SampleState SampleInput -> WB.Binding SampleState SampleInput) -> IO ()
+checkMappend append_op = do
+  out_ref <- newStrRef
+  rand_binding <- generate $ genStatelessBinding out_ref
+  let execute b = void $ inputAll b (SS "") =<< generate (listOf arbitrary)
+  execute rand_binding
+  out_orig <- readIORef out_ref
+  writeIORef out_ref []
+  execute (append_op rand_binding)
+  readIORef out_ref `shouldReturn` out_orig
+
+actRun :: Maybe (WB.Action IO a) -> IO ()
+actRun = void . WB.actDo . fromJust
+
+checkInputsS :: (Show i, Eq i) => s -> [i] -> State.StateT (WB.Binding s i) IO ()
+checkInputsS state exp_in = State.get >>= \b -> lift $ WB.boundInputs b state `shouldMatchList` exp_in
+
+checkInputsS' :: (Show i, Eq i) => [i] -> State.StateT (WB.Binding SampleState i) IO ()
+checkInputsS' = checkInputsS (SS "")
+
+evalStateEmpty :: State.StateT (WB.Binding SampleState SampleInput) IO () -> IO ()
+evalStateEmpty s = State.evalStateT s mempty_stateless
+
+spec :: Spec
+spec = do
+  spec_stateless
+  spec_conversions
+  spec_convBack
+  spec_stateful
+  spec_extend
+  spec_conditionBoth
+  spec_monadic
+
+spec_stateless :: Spec
+spec_stateless = do
+  describe "Binding (Monoid instances)" $ do
+    it "mempty returns empty binding" $ property
+      ( isNothing <$> (WB.boundAction mempty_stateless <$> arbitrary <*> arbitrary) )
+    it "mempty `mappend` random == mempty" $ do
+      checkMappend (mempty <>)
+    it "random `mappend` mempty == mempty" $ do
+      checkMappend (<> mempty)
+  describe "binding" $ do
+    it "returns a stateless Binding" $ withStrRef $ \out checkOut -> do
+      let b = WB.binding [outOn out SIa 'A', outOn out SIb 'B']
+      WB.boundInputs b (SS "") `shouldMatchList` [SIa, SIb]
+      WB.boundAction b (SS "") SIc `shouldSatisfy` isNothing
+      actRun $ WB.boundAction b (SS "") SIa
+      checkOut "A"
+      actRun $ WB.boundAction b (SS "") SIb
+      checkOut "AB"
+    it "prefers the latter action if multiple actions are bound to the same input" $ withStrRef $ \out checkOut -> do
+      let b = WB.binding [ outOn out SIa '1',
+                           outOn out SIa '2',
+                           outOn out SIa '3'
+                         ]
+      actRun $ WB.boundAction b (SS "") SIa
+      checkOut "3"
+  describe "whenFront" $ do
+    it "adds a condition on the front-end state" $ withStrRef $ \out checkOut -> do
+      let b = WB.whenFront (\(SS s) -> s == "hoge") $ WB.binding [outOn out SIa 'A']
+      WB.boundInputs b (SS "") `shouldMatchList` []
+      WB.boundAction b (SS "") SIa `shouldSatisfy` isNothing
+      WB.boundInputs b (SS "foobar") `shouldMatchList` []
+      WB.boundAction b (SS "foobar") SIa `shouldSatisfy` isNothing
+      WB.boundInputs b (SS "hoge") `shouldMatchList` [SIa]
+      actRun $ WB.boundAction b (SS "hoge") SIa
+      checkOut "A"
+    it "is AND condition" $ withStrRef $ \out checkOut -> do
+      let raw_b = WB.binding [outOn out SIa 'A']
+          b = WB.whenFront ((<= 5) . length . unSS) $ WB.whenFront ((3 <=) . length . unSS) $ raw_b
+      WB.boundInputs b (SS "ho") `shouldMatchList` []
+      WB.boundAction b (SS "ho") SIa `shouldSatisfy` isNothing
+      WB.boundInputs b (SS "hogehoge") `shouldMatchList` []
+      WB.boundAction b (SS "hogehoge") SIa `shouldSatisfy` isNothing
+      WB.boundInputs b (SS "hoge") `shouldMatchList` [SIa]
+      actRun $ WB.boundAction b (SS "hoge") SIa
+      checkOut "A"
+    it "should be effective for derived Bindings" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let raw_b = WB.binding [outOn out SIa 'A']
+      State.put $ WB.whenFront (\(SS s) -> s == "foobar") $ raw_b
+      checkInputsS (SS "hoge") []
+      checkInputsS (SS "foobar") [SIa]
+      execAll (SS "foobar") [SIa]
+      checkOut "A"
+      checkInputsS (SS "hoge") []
+      checkInputsS (SS "foobar") [SIa]
+  describe "ifFront" $ do
+    it "chooses from independent Bindings" $ withStrRef $ \out checkOut -> do
+      let b = WB.ifFront (\(SS s) -> length s <= 5)
+              (WB.binding [outOn out SIa 'A']) (WB.binding [outOn out SIb 'B'])
+      WB.boundInputs b (SS "hoge") `shouldMatchList` [SIa]
+      WB.boundInputs b (SS "foobar") `shouldMatchList` [SIb]
+      actRun $ WB.boundAction b (SS "foobar") SIb
+      checkOut "B"
+    it "adds AND conditions when nested" $ withStrRef $ \out checkOut -> do
+      let b1 = WB.ifFront (\(SS s) -> length s <= 5)
+               (WB.binding [outOn out SIa 'A']) (WB.binding [outOn out SIb 'B'])
+          b = WB.ifFront (\(SS s) -> length s >= 3) b1 $ WB.binding [outOn out SIc 'C']
+      WB.boundInputs b (SS "") `shouldMatchList` [SIc]
+      WB.boundInputs b (SS "foo") `shouldMatchList` [SIa]
+      WB.boundInputs b (SS "hoge") `shouldMatchList` [SIa]
+      WB.boundInputs b (SS "foobar") `shouldMatchList` [SIb]
+      actRun $ WB.boundAction b (SS "ho") SIc
+      checkOut "C"
+  describe "Binding (mappend)" $ do
+    it "combines two stateless Bindings" $ withStrRef $ \out checkOut -> do
+      let b1 = WB.binding [outOn out SIa 'A']
+          b2 = WB.binding [outOn out SIb 'B']
+          b = b1 <> b2
+      WB.boundInputs b (SS "") `shouldMatchList` [SIa, SIb]
+      void $ inputAll b (SS "") [SIa, SIb]
+      checkOut "AB"
+    it "front-end conditions are preserved" $ withStrRef $ \out _ -> do
+      let b1 = WB.whenFront ((3 <=) . length . unSS) $ WB.binding [outOn out SIa 'A']
+          b2 = WB.whenFront ((<= 5) . length . unSS) $ WB.binding [outOn out SIb 'B']
+          b = b1 <> b2
+      WB.boundInputs b (SS "aa") `shouldMatchList` [SIb]
+      WB.boundInputs b (SS "aabb") `shouldMatchList` [SIa, SIb]
+      WB.boundInputs b (SS "aabbcc") `shouldMatchList` [SIa]
+    it "prefers the latter Binding" $ withStrRef $ \out checkOut -> do
+      let b1 = WB.binding [outOn out SIa '1', outOn out SIb 'B']
+          b2 = WB.binding [outOn out SIa '2']
+          b = b1 <> b2
+      WB.boundInputs b (SS "") `shouldMatchList` [SIa, SIb]
+      actRun $ WB.boundAction b (SS "") SIa
+      checkOut "2"
+    it "preserves implicit back-end states" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let b1 = WB.startFrom (SB 0)
+               $ WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa '0' (\_ -> SB 1)])
+               $ WB.ifBack (== (SB 1)) (WB.binding' [outOnS out SIa '1' (\_ -> SB 0)])
+               $ mempty
+          b2 = WB.startFrom (SB 0)
+               $ WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIb '2' (\_ -> SB 1)])
+               $ WB.ifBack (== (SB 1)) (WB.binding' [outOnS out SIb '3' (\_ -> SB 0)])
+               $ mempty
+      State.put (b1 <> b2)
+      checkInputsS (SS "") [SIa, SIb]
+      execAll (SS "") [SIa]
+      checkOut "0"
+      checkInputsS (SS "") [SIa, SIb]
+      execAll (SS "") [SIb]
+      checkOut "02"
+      checkInputsS (SS "") [SIa, SIb]
+      execAll (SS "") [SIa]
+      checkOut "021"
+      checkInputsS (SS "") [SIa, SIb]
+      execAll (SS "") [SIb]
+      checkOut "0213"
+      checkInputsS (SS "") [SIa, SIb]
+      execAll (SS "") [SIa]
+      checkOut "02130"
+
+spec_conversions :: Spec
+spec_conversions = do
+  describe "convFront" $ do
+    it "converts front-end state" $ withStrRef $ \out checkOut -> do
+      let orig_b = WB.whenFront (("hoge" ==) . unSS) $ WB.binding [outOn out SIa 'A']
+          b = WB.convFront SS orig_b
+      WB.boundInputs b "" `shouldMatchList` []
+      WB.boundInputs b "hoge" `shouldMatchList` [SIa]
+      actRun $ WB.boundAction b "hoge" SIa
+      checkOut "A"
+  describe "convInput" $ do
+    it "converts input symbols" $ withStrRef $ \out checkOut -> do
+      let orig_b = WB.binding [outOn out SIa 'A']
+          b = WB.convInput show orig_b
+      WB.boundInputs b (SS "") `shouldMatchList` ["SIa"]
+      actRun $ WB.boundAction b (SS "") "SIa"
+      checkOut "A"
+  describe "advice" $ do
+    it "converts all actions in Binder" $ withStrRef $ \out checkOut -> do
+      let convert_action a = a { WB.actDescription = WB.actDescription a <> "!!",
+                                 WB.actDo = WB.actDo a >> (modifyIORef out (++ "!"))
+                               }
+          b = WB.binds $ WB.advice convert_action $ do
+            WB.on SIa `WB.as` "action a" `WB.run` modifyIORef out (++ "A")
+            WB.on SIb `WB.as` "action b" `WB.run` modifyIORef out (++ "B")
+      (WB.actDescription <$> WB.boundAction b () SIa) `shouldBe` Just "action a!!"
+      (WB.actDescription <$> WB.boundAction b () SIb) `shouldBe` Just "action b!!"
+      void $ inputAll b () [SIa]
+      checkOut "A!"
+      void $ inputAll b () [SIb]
+      checkOut "A!B!"
+    it "preserves the order of binding." $ withStrRef $ \out checkOut -> do
+      let b = WB.binds $ WB.advice (WB.before $ modifyIORef out (++ "A")) $ do
+            WB.on SIa `WB.run` modifyIORef out (++ "1")
+            WB.on SIa `WB.run` modifyIORef out (++ "2")
+            WB.on SIa `WB.run` modifyIORef out (++ "3")
+      void $ inputAll b () [SIa]
+      checkOut "A3"
+    it "can nest" $ withStrRef $ \out checkOut -> do
+      let b = WB.binds $ do
+            WB.on SIa `WB.run` modifyIORef out (++ "1")
+            WB.advice (WB.before $ modifyIORef out (++ "*")) $ do
+              WB.on SIb `WB.run` modifyIORef out (++ "3")
+              WB.advice (WB.after $ modifyIORef out (++ "@")) $ do
+                WB.on SIa `WB.run` modifyIORef out (++ "4")
+                WB.on SIc `WB.run` modifyIORef out (++ "5")
+              WB.advice (WB.after $ modifyIORef out (++ "#")) $ do
+                WB.on SIb `WB.run` modifyIORef out (++ "6")
+                WB.on SIc `WB.run` modifyIORef out (++ "7")
+              WB.on SIa `WB.run` modifyIORef out (++ "8")
+      void $ inputAll b () [SIa]
+      checkOut "*8"
+      void $ inputAll b () [SIb]
+      checkOut "*8*6#"
+      void $ inputAll b () [SIc]
+      checkOut "*8*6#*7#"
+  describe "before" $ do
+    it "prepends a monadic action" $ withStrRef $ \out checkOut -> do
+      let act = WB.Action { WB.actDescription = "desc",
+                            WB.actDo = modifyIORef out (++ "ORIG")
+                          }
+          got = WB.before (modifyIORef out (++ "before")) act
+      WB.actDescription got `shouldBe` "desc"
+      WB.actDo got
+      checkOut "beforeORIG"
+  describe "after" $ do
+    it "appends a monadic action" $ withStrRef $ \out checkOut -> do
+      let act = WB.Action { WB.actDescription = "desc",
+                            WB.actDo = modifyIORef out (++ "ORIG")
+                          }
+          got = WB.after (modifyIORef out (++ "after")) act
+      WB.actDescription got `shouldBe` "desc"
+      WB.actDo got
+      checkOut "ORIGafter"
+
+spec_convBack :: Spec
+spec_convBack = do
+  describe "convBack" $ do
+    it "can convert the back-end state by isomorphism" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let act = do
+            out_elem <- head <$> show <$> unSB <$> State.get
+            liftIO $ modifyIORef out (++ [out_elem])
+            State.modify succ
+          orig_b = WB.binding' [(SIa, WB.Action "" act)]
+          b = WB.convBack (\s _-> unSB s) SB orig_b
+      State.put $ WB.startFrom 0 b
+      checkInputsS' [SIa]
+      execAll' [SIa]
+      checkOut "0"
+      execAll' [SIa]
+      checkOut "01"
+      execAll' [SIa]
+      checkOut "012"
+    it "can convert the back-end state by a lens" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let bl = WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa '0' (\_ -> SB 1)])
+               $ WB.whenBack (== (SB 1)) (WB.binding' [outOnS out SIa '1' (\_ -> SB 0)])
+          br = WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIb '2' (\_ -> SB 1)])
+               $ WB.whenBack(== (SB 1)) (WB.binding' [outOnS out SIb '3' (\_ -> SB 0)])
+          bg = WB.whenBack (== (BSB (SB 0) (SB 0))) $ WB.binding' [outOnS out SIc '4' (\_ -> BSB (SB 1) (SB 1))]
+          convBackByLens :: Lens.Lens' s a -> WB.Binding' a f i -> WB.Binding' s f i
+          convBackByLens l = WB.convBack (Lens.set l) (view l)
+          b = (convBackByLens lSB bl) <> (convBackByLens rSB br) <> bg
+      State.put $ WB.startFrom (BSB (SB 0) (SB 0)) b
+      checkInputsS' [SIa, SIb, SIc]
+      execAll' [SIa]
+      checkOut "0"
+      checkInputsS' [SIa, SIb]
+      execAll' [SIb]
+      checkOut "02"
+      checkInputsS' [SIa, SIb]
+      execAll' [SIb]
+      checkOut "023"
+      checkInputsS' [SIa, SIb]
+      execAll' [SIa]
+      checkOut "0231"
+      checkInputsS' [SIa, SIb, SIc]
+      execAll' [SIc]
+      checkOut "02314"
+      checkInputsS' [SIa, SIb]
+      execAll' [SIa, SIb]
+      checkOut "0231413"
+    
+
+spec_stateful :: Spec
+spec_stateful = do
+  describe "binding'" $ do
+    it "returns a stateful Binding" $ withStrRef $ \out checkOut -> do
+      let act = do
+            out_elem <- head <$> show <$> unSB <$> State.get
+            liftIO $ modifyIORef out (++ [out_elem])
+            State.modify succ
+          b = WB.binding' [(SIa, WB.Action "" act)]
+      WB.boundInputs' b (SB 0)  (SS "") `shouldBe` [SIa]
+      WB.boundInputs' b (SB 10) (SS "hoge") `shouldBe` [SIa]
+      void $ inputAll (WB.startFrom (SB 0) b) (SS "") $ replicate 12 SIa
+      checkOut "012345678911"
+    it "prefers the latter action if multiple actions are bound to the same input" $ withStrRef $ \out checkOut -> do
+      let b = WB.startFrom (SB 0) $ WB.binding' [ outOn out SIa '1',
+                                                  outOn out SIa '2',
+                                                  outOn out SIa '3'
+                                                ]
+      actRun $ WB.boundAction b (SS "") SIa
+      checkOut "3"
+    it "can create a stateful Binding with different bound inputs for different back-end state" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      State.put $ WB.startFrom (SB 0)
+        $ WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa 'A' (\_ -> SB 1)])
+        $ WB.ifBack (== (SB 1)) (WB.binding' [outOnS out SIb 'B' (\_ -> SB 2)])
+        $ WB.ifBack (== (SB 2)) (WB.binding' [outOnS out SIc 'C' (\_ -> SB 0)])
+        $ mempty
+      checkOut ""
+      checkInputsS (SS "") [SIa]
+      execAll (SS "") [SIa]
+      checkOut "A"
+      checkInputsS (SS "") [SIb]
+      execAll (SS "") [SIb]
+      checkOut "AB"
+      checkInputsS (SS "") [SIc]
+      execAll (SS "") [SIc]
+      checkOut "ABC"
+      checkInputsS (SS "") [SIa]
+  describe "Binding (mappend, stateful)" $ do
+    it "shares the explicit back-end state" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let b1 = WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa 'A' (\_ -> SB 1)])
+               $ WB.ifBack (== (SB 1)) ( WB.binding' [outOnS out SIb 'B' (\_ -> SB 2),
+                                                    outOnS out SIc 'b' (\_ -> SB 2)]
+                                       )
+               $ WB.ifBack (== (SB 2)) (WB.binding' [outOnS out SIc 'C' (\_ -> SB 0)])
+               $ mempty
+          b2 = WB.whenBack (== (SB 1)) $ WB.binding' [outOnS out SIb 'D' (\_ -> SB 0)]
+          b = b1 <> b2
+      State.put $ WB.startFrom (SB 0) b
+      checkInputsS (SS "") [SIa]
+      execAll (SS "") [SIa]
+      checkOut "A"
+      checkInputsS (SS "") [SIb, SIc]
+      execAll (SS "") [SIb]
+      checkOut "AD"
+      checkInputsS (SS "") [SIa]
+      execAll (SS "") [SIa, SIc]
+      checkOut "ADAb"
+      checkInputsS (SS "") [SIc]
+      execAll (SS "") [SIc]
+      checkOut "ADAbC"
+      checkInputsS (SS "") [SIa]
+      
+  describe "ifBack" $ do
+    it "chooses from unconditional bindings" $ withStrRef $ \out checkOut -> do
+      let b = WB.ifBack (\(SB sb) -> sb < 5)
+              (WB.binding [outOn out SIa 'A']) (WB.binding [outOn out SIb 'B'])
+          ba = WB.startFrom (SB 4) b
+          bb = WB.startFrom (SB 5) b
+      WB.boundInputs ba (SS "") `shouldMatchList` [SIa]
+      actRun $ WB.boundAction ba (SS "") SIa
+      checkOut "A"
+      WB.boundInputs bb (SS "") `shouldMatchList` [SIb]
+      actRun $ WB.boundAction bb (SS "") SIb
+      checkOut "AB"
+    it "combines an extended stateless binding with a stateful binding" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let b_stateless = WB.binding [outOn out SIa 'A']
+          b = WB.ifBack (\(SB sb) -> sb < 5)
+              (b_stateless <> WB.binding' [outOnS out SIb 'B' $ const (SB 10)])
+              $ WB.binding' [outOnS out SIc 'C' $ const (SB 3)]
+      State.put $ WB.startFrom (SB 0) b
+      checkInputsS' [SIa, SIb]
+      execAll' [SIa]
+      checkOut "A"
+      checkInputsS' [SIa, SIb]
+      execAll' [SIb]
+      checkOut "AB"
+      checkInputsS' [SIc]
+      execAll' [SIc]
+      checkOut "ABC"
+      checkInputsS' [SIa, SIb]
+    it "combines implicit stateful binding with a binding with newly introduced states" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let b1 = WB.startFrom (SB 0)
+               $ WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa 'A' $ const (SB 1)])
+               $ WB.binding' [outOnS out SIb 'B' $ const (SB 0)]
+          b = WB.startFrom (SB 0)
+              $ WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa 'a' $ const (SB 1)])
+              $ WB.extend b1 <> WB.binding' [outOnS out SIc 'c' $ const (SB 0)]
+      State.put b
+      checkInputsS' [SIa]
+      execAll' [SIa]
+      checkOut "a"
+      checkInputsS' [SIa, SIc]
+      execAll' [SIa]
+      checkOut "aA"
+      checkInputsS' [SIb, SIc]
+      execAll' [SIb]
+      checkOut "aAB"
+      checkInputsS' [SIa, SIc]
+      execAll' [SIc]
+      checkOut "aABc"
+      checkInputsS' [SIa]
+
+  describe "whenBack" $ do
+    it "adds a condition to the back-end state" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let raw_b = WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa '0' (\_ -> SB 1)])
+                  $ WB.ifBack (== (SB 1)) (WB.binding' [outOnS out SIb '1' (\_ -> SB 0)])
+                  $ mempty
+          b = WB.whenBack (== SB 0) $ raw_b
+      State.put $ WB.startFrom (SB 0) b
+      checkInputsS' [SIa]
+      execAll' [SIa]
+      checkOut "0"
+      checkInputsS' []
+
+spec_extend :: Spec
+spec_extend = do
+  describe "extend" $ do
+    it "extends a stateless Binding" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let bl :: WB.Binding SampleState SampleInput
+          bl = WB.binding [
+            outOn out SIa 'a',
+            outOn out SIb 'b',
+            outOn out SIc 'c']
+          bs = WB.ifBack (== (SB 0)) (WB.binding' [outOnS out SIa 'A' (\_ -> SB 1)])
+               $ WB.ifBack (== (SB 1)) (WB.binding' [outOnS out SIb 'B' (\_ -> SB 2)])
+               $ WB.ifBack (== (SB 2)) (WB.binding' [outOnS out SIc 'C' (\_ -> SB 0)])
+               $ mempty
+      State.put $ WB.startFrom (SB 0) $ (WB.extend bl <> bs)
+      checkInputsS' [SIa, SIb, SIc]
+      execAll' [SIb, SIc, SIa]
+      checkOut "bcA"
+      checkInputsS' [SIa, SIb, SIc]
+      execAll' [SIa, SIc, SIb]
+      checkOut "bcAacB"
+      checkInputsS' [SIa, SIb, SIc]
+      execAll' [SIa, SIb, SIc]
+      checkOut "bcAacBabC"
+
+spec_conditionBoth :: Spec
+spec_conditionBoth = do
+  describe "ifBoth" $ do
+    it "chooses bindings according to front-end and back-end states" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let b = WB.ifBoth (\ _ (SS fs) -> fs == "hoge") ( WB.binding' [ outOnS out SIa 'a' (SB . succ . unSB),
+                                                                      outOnS out SIb 'b' (const $ SB 0)
+                                                                    ]
+                                                    )
+              $ WB.ifBoth (\ (SB bs) (SS fs) -> length fs < bs)
+                (WB.binding' [ outOnS out SIc 'c' (SB . pred . unSB) ])
+                (WB.binding' [ outOnS out SIb 'B' (SB . succ . unSB) ])
+      State.put $ WB.startFrom (SB 10) $ b
+      checkInputsS (SS "hoge") [SIa, SIb]
+      checkInputsS (SS "") [SIc]
+      checkInputsS (SS "foooooobaaaaaa") [SIb]
+      execAll (SS "hoge") [SIb]
+      checkOut "b"
+      checkInputsS (SS "") [SIb]
+      execAll (SS "") [SIb]
+      checkOut "bB"
+      checkInputsS (SS "hoge") [SIa, SIb]
+      checkInputsS (SS "") [SIc]
+      checkInputsS (SS "a") [SIb]
+      execAll (SS "") [SIc]
+      checkOut "bBc"
+      checkInputsS (SS "hoge") [SIa, SIb]
+      checkInputsS (SS "") [SIb]
+      checkInputsS (SS "a") [SIb]
+      execAll (SS "hoge") $ replicate 5 SIa
+      checkOut "bBcaaaaa"
+      checkInputsS (SS "hoge") [SIa, SIb]
+      checkInputsS (SS "fooo") [SIc]
+      checkInputsS (SS "foooo") [SIb]
+            
+  describe "whenBoth" $ do
+    let incr' out ret = outOnS out SIa ret (\(SB num) -> SB (num + 1))
+        decr' out ret = outOnS out SIb ret (\(SB num) -> SB (num - 1))
+    it "adds a condition to both front-end and back-end states" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let incr = incr' out
+          decr = decr' out
+          raw_b = WB.ifBack (== (SB 0)) (WB.binding' [incr '+']) (WB.binding' [incr '+', decr '-'])
+          b = WB.whenBoth (\(SB num) (SS str) -> length str == num) $ raw_b
+      State.put $ WB.startFrom (SB 0) $ b
+      checkInputsS (SS "hoge") []
+      checkInputsS (SS "") [SIa]
+      execAll (SS "") [SIa]
+      checkOut "+"
+      checkInputsS (SS "") []
+      checkInputsS (SS "e") [SIa, SIb]
+      execAll (SS "e") [SIa]
+      checkOut "++"
+      checkInputsS (SS "e") []
+      checkInputsS (SS "eg") [SIa, SIb]
+      execAll (SS "eg") [SIb]
+      checkOut "++-"
+      checkInputsS (SS "e") [SIa, SIb]
+    it "creates independent conditions when combined with <>" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      let incr = incr' out
+          decr = decr' out
+          bn = WB.ifBack (== (SB 0)) (WB.binding' [incr '+']) (WB.binding' [incr '+', decr '-'])
+          bn' = WB.whenBoth (\(SB num) (SS str) -> length str == num) bn
+          ba = WB.ifBack (== (SB 0)) (WB.binding' [incr 'p']) (WB.binding' [incr 'p', decr 'm'])
+          ba' = WB.whenBoth (\(SB num) (SS str) -> read str == num) ba
+      State.put $ WB.startFrom (SB 1) (bn' <> ba')
+      checkInputsS (SS "10") []
+      checkInputsS (SS "4") [SIa, SIb]
+      execAll (SS "4") [SIa]
+      checkOut "+"
+      checkInputsS (SS "2") [SIa, SIb]
+      execAll (SS "2") [SIa]
+      checkOut "+p"
+      checkInputsS (SS "342") [SIa, SIb]
+      execAll (SS "342") [SIb]
+      checkOut "+p-"
+      execAll (SS "2") [SIb]
+      checkOut "+p-m"
+      checkInputsS (SS "1") [SIa, SIb]
+      execAll (SS "1") [SIb]
+      checkOut "+p-mm"
+      
+spec_monadic :: Spec
+spec_monadic = describe "Monadic construction of Binding" $ do
+  describe "binds" $ do
+    it "constructs stateless Binding" $ withStrRef $ \out checkOut -> do
+      let putOut c = modifyIORef out (++ [c])
+          b = WB.binds $ do
+            WB.on SIa `WB.run` putOut 'a'
+            WB.on SIb `WB.run` do
+              putOut 'b'
+              putOut 'B'
+      actRun $ WB.boundAction b (SS "") SIa
+      checkOut "a"
+      actRun $ WB.boundAction b (SS "") SIb
+      checkOut "abB"
+    it "prefers the latter action if multiple actions are bound to the same input" $ withStrRef $ \out checkOut -> do
+      let b = WB.binds $ do
+            WB.on SIa `WB.run` modifyIORef out (++ "1")
+            WB.on SIa `WB.run` modifyIORef out (++ "2")
+            WB.on SIa `WB.run` modifyIORef out (++ "3")
+      actRun $ WB.boundAction b (SS "") SIa
+      checkOut "3"
+  describe "Binder" $ do
+    it "can bind actions with different result types" $ withStrRef $ \out checkOut -> do
+      let ret_b :: String
+          ret_b = "return by b"
+          b = WB.binds $ do  -- it's ok if it compiles..
+            WB.on SIa `WB.run` do
+              modifyIORef out (++ "a")
+              return ()
+            WB.on SIb `WB.run` do
+              modifyIORef out (++ "b")
+              return ret_b
+      actRun $ WB.boundAction b (SS "") SIb
+      checkOut "b"
+  describe "binds'" $ do
+    it "constructs stateful Binding" $ evalStateEmpty $ withStrRef $ \out checkOut -> do
+      State.put $ WB.startFrom (SB 0) $ WB.binds' $ do
+        WB.on SIa `WB.run` (State.modify $ \(SB v) -> SB (v + 1))
+        WB.on SIb `WB.run` (State.modify $ \(SB v) -> SB (v - 1))
+        WB.on SIc `WB.run` do
+          (SB cur) <- State.get
+          liftIO $ modifyIORef out (++ show cur)
+      execAll' [SIa, SIa, SIa]
+      checkOut ""
+      execAll' [SIc]
+      checkOut "3"
+      execAll' [SIb, SIb]
+      checkOut "3"
+      execAll' [SIc]
+      checkOut "31"
+    it "prefers the latter action if multiple actions are bound to the same input" $ withStrRef $ \out checkOut -> do
+      let b = WB.startFrom (SB 0) $ WB.binds' $ do
+            WB.on SIa `WB.run` (liftIO $ modifyIORef out (++ "1"))
+            WB.on SIa `WB.run` (liftIO $ modifyIORef out (++ "2"))
+            WB.on SIa `WB.run` (liftIO $ modifyIORef out (++ "3"))
+      actRun $ WB.boundAction b (SS "") SIa
+      checkOut "3"
+  describe "as" $ do
+    it "sets ActionDescription" $ do
+      let b = WB.binds $ do
+            WB.on SIa `WB.as` "action for a" `WB.run` return ()
+            WB.on SIb `WB.as` "action for b" `WB.run` return ()
+      (WB.actDescription <$> WB.boundAction b (SS "") SIa) `shouldBe` Just "action for a"
+      (WB.actDescription <$> WB.boundAction b (SS "") SIb) `shouldBe` Just "action for b"
+      (WB.actDescription <$> WB.boundAction b (SS "") SIc) `shouldBe` Nothing
+
diff --git a/test/WildBind/ExecSpec.hs b/test/WildBind/ExecSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/WildBind/ExecSpec.hs
@@ -0,0 +1,234 @@
+module WildBind.ExecSpec (main, spec) where
+
+import Control.Applicative ((<$>))
+import Control.Concurrent (forkIOWithUnmask, killThread, threadDelay)
+import Control.Concurrent.STM (atomically, TChan, readTChan, tryReadTChan, writeTChan, newTChanIO)
+import Control.Exception (bracket, throw, fromException)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import qualified Control.Monad.Trans.State as State
+import Data.Monoid ((<>))
+import System.IO.Error (userError)
+import Test.Hspec
+
+import qualified WildBind.Binding as WBB
+import qualified WildBind.Exec as WBE
+import qualified WildBind.FrontEnd as WBF
+
+import WildBind.ForTest (SampleInput(..), SampleState(..), SampleBackState(..))
+
+newtype EventChan s i = EventChan { unEventChan :: TChan (WBF.FrontEvent s i) }
+
+data GrabHistory i = GSet i | GUnset i deriving (Show, Eq, Ord)
+
+newtype GrabChan i = GrabChan { unGrabChan :: TChan (GrabHistory i) }
+
+frontEnd :: EventChan s i -> GrabChan i -> WBF.FrontEnd s i
+frontEnd echan gchan = WBF.FrontEnd
+  { WBF.frontDefaultDescription = const "",
+    WBF.frontSetGrab = \i -> atomically $ writeTChan (unGrabChan gchan) (GSet i),
+    WBF.frontUnsetGrab = \i -> atomically $ writeTChan (unGrabChan gchan) (GUnset i),
+    WBF.frontNextEvent = atomically $ readTChan $ unEventChan echan
+  }
+
+_write :: MonadIO m => TChan a -> a -> m ()
+_write tc = liftIO . atomically . writeTChan tc
+
+outChanOn :: MonadIO m => TChan a -> i -> a -> (i, WBB.Action m ())
+outChanOn out_chan input out_elem = (input, WBB.Action "" (out_chan `_write` out_elem))
+
+outChanOnS :: TChan a -> i -> a -> bs -> (i, WBB.Action (State.StateT bs IO) ())
+outChanOnS out_chan input out_elem next_state = (,) input $ WBB.Action "" $ do
+  liftIO $ atomically $ writeTChan out_chan out_elem
+  State.put next_state
+
+withWildBind' :: Ord i => (WBF.FrontEnd s i -> IO ()) -> (EventChan s i -> GrabChan i -> IO ()) -> IO ()
+withWildBind' exec action = do
+  echan <- EventChan <$> newTChanIO
+  gchan <- GrabChan <$> newTChanIO
+  let spawnWildBind = forkIOWithUnmask $ \umask -> umask $ exec (frontEnd echan gchan)
+  bracket spawnWildBind killThread (\_ -> action echan gchan)
+  
+withWildBind :: Ord i => WBB.Binding s i -> (EventChan s i -> GrabChan i -> IO ()) -> IO ()
+withWildBind binding action = withWildBind' (WBE.wildBind binding) action
+
+emitEvent :: TChan (WBF.FrontEvent s i) -> WBF.FrontEvent s i -> IO ()
+emitEvent chan event = atomically $ writeTChan chan event
+
+shouldProduce :: (Show a, Eq a) => TChan a -> a -> IO ()
+shouldProduce chan expectation = (atomically $ readTChan chan) `shouldReturn` expectation
+
+readAll :: TChan a -> IO [a]
+readAll chan = atomically $ readAll' [] where
+  readAll' acc = do
+    mret <- tryReadTChan chan
+    case mret of
+      Nothing -> return (reverse acc)
+      Just ret -> readAll' (ret : acc)
+
+shouldNowMatch :: (Show a, Eq a) => TChan a -> [a] -> IO ()
+shouldNowMatch chan expectation = readAll chan >>= (`shouldMatchList` expectation)
+
+changeAndInput :: s -> i -> [WBF.FrontEvent s i]
+changeAndInput s i = [WBF.FEChange s, WBF.FEInput i]
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = do
+  wildBindSpec
+  optionSpec
+
+wildBindSpec :: Spec
+wildBindSpec = do
+  describe "wildBind" $ do
+    it "should enable input grabs" $ do
+      ochan <- newTChanIO
+      let b = WBB.binding [outChanOn ochan SIa 'A',
+                           outChanOn ochan SIb 'B']
+      withWildBind b $ \(EventChan echan) (GrabChan gchan) -> do
+        emitEvent echan $ WBF.FEChange $ SS ""
+        emitEvent echan $ WBF.FEInput SIa
+        ochan `shouldProduce` 'A'
+        ghist <- readAll gchan
+        ghist `shouldMatchList` [GSet SIa, GSet SIb]
+    it "should enable/disable grabs when the front-end state changes" $ do
+      ochan <- newTChanIO
+      let b = (WBB.whenFront (\(SS s) -> s == "A") $ WBB.binding [outChanOn ochan SIa 'A'])
+              <>
+              (WBB.whenFront (\(SS s) -> s == "B") $ WBB.binding [outChanOn ochan SIb 'B'])
+              <>
+              (WBB.whenFront (\(SS s) -> s == "C") $ WBB.binding [outChanOn ochan SIc 'C'])
+      withWildBind b $ \(EventChan echan) (GrabChan gchan) -> do
+        mapM_ (emitEvent echan) $ changeAndInput (SS "A") SIa
+        ochan `shouldProduce` 'A'
+        gchan `shouldNowMatch` [GSet SIa]
+        mapM_ (emitEvent echan) $ changeAndInput (SS "B") SIb
+        ochan `shouldProduce` 'B'
+        gchan `shouldNowMatch` [GUnset SIa, GSet SIb]
+        mapM_ (emitEvent echan) $ changeAndInput (SS "C") SIc
+        ochan `shouldProduce` 'C'
+        gchan `shouldNowMatch` [GUnset SIb, GSet SIc]
+        emitEvent echan $ WBF.FEChange (SS "")
+        threadDelay 10000
+        gchan `shouldNowMatch` [GUnset SIc]
+    it "should enable/disable grabs when the back-end state changes" $ do
+      ochan <- newTChanIO
+      let b' = WBB.ifBack (== (SB 0)) (WBB.binding' [outChanOnS ochan SIa 'A' (SB 1)])
+               $ WBB.whenBack (== (SB 1)) (WBB.binding' [outChanOnS ochan SIb 'B' (SB 0)])
+          b = WBB.startFrom (SB 0) b'
+      withWildBind b $ \(EventChan echan) (GrabChan gchan) -> do
+        emitEvent echan $ WBF.FEChange (SS "")
+        threadDelay 10000
+        gchan `shouldNowMatch` [GSet SIa]
+        emitEvent echan $ WBF.FEInput SIa
+        ochan `shouldProduce` 'A'
+        threadDelay 10000
+        gchan `shouldNowMatch` [GUnset SIa, GSet SIb]
+        emitEvent echan $ WBF.FEInput SIb
+        ochan `shouldProduce` 'B'
+        threadDelay 10000
+        gchan `shouldNowMatch` [GUnset SIb, GSet SIa]
+    it "should crush exceptions from bound actions" $ do
+      ochan <- newTChanIO
+      let b = WBB.binds $ do
+            WBB.on SIa `WBB.run` (fail "ERROR!!")
+            WBB.on SIb `WBB.run` (atomically $ writeTChan ochan 'b')
+      withWildBind b $ \(EventChan echan) _ -> do
+        emitEvent echan $ WBF.FEChange (SS "")
+        emitEvent echan $ WBF.FEInput SIa
+        emitEvent echan $ WBF.FEInput SIb
+        ochan `shouldProduce` 'b'
+    it "should keep the current back-state when exception is thrown from bound actions" $ do
+      ochan <- newTChanIO
+      let killing_b = WBB.binds' $ WBB.on SIa `WBB.run` do
+            State.put (SB 0)
+            liftIO $ fail "ERROR!"
+          b = WBB.startFrom (SB 0) $ (killing_b <>)
+              $ WBB.ifBack (== SB 0)
+              ( WBB.binds' $ WBB.on SIb `WBB.run` do
+                   liftIO $ atomically $ writeTChan ochan 'b'
+                   State.put (SB 1)
+              )
+              ( WBB.binds' $ WBB.on SIc `WBB.run` do
+                   liftIO $ atomically $ writeTChan ochan 'c'
+                   State.put (SB 0)
+              )
+      withWildBind b $ \(EventChan echan) (GrabChan gchan) -> do
+        emitEvent echan $ WBF.FEChange (SS "")
+        emitEvent echan $ WBF.FEInput SIa
+        emitEvent echan $ WBF.FEInput SIb
+        ochan `shouldProduce` 'b'
+        gchan `shouldNowMatch` [GSet SIa, GSet SIb,  GUnset SIb, GSet SIc]
+        emitEvent echan $ WBF.FEInput SIa
+        emitEvent echan $ WBF.FEInput SIc
+        ochan `shouldProduce` 'c'
+        gchan `shouldNowMatch` [GUnset SIc, GSet SIb]
+
+
+shouldNextMatch :: (Show a, Eq a) => TChan [a] -> [a] -> IO ()
+shouldNextMatch tc expected = do
+  got <- atomically $ readTChan tc
+  got `shouldMatchList` expected
+
+optionSpec :: Spec
+optionSpec = do
+  describe "optBindingHook" $ do
+    it "hooks change of binding because front-end state changes" $ do
+      hook_chan <- newTChanIO
+      out_chan <- newTChanIO
+      let opt = WBE.defOption { WBE.optBindingHook = _write hook_chan }
+          b = WBB.whenFront (== SS "hoge")
+              $ WBB.binding [ (SIa, WBB.Action "a button" (out_chan `_write` 'a')),
+                              (SIb, WBB.Action "b button" (out_chan `_write` 'b'))
+                            ]
+      withWildBind' (WBE.wildBind' opt b) $ \(EventChan echan) (GrabChan gchan) -> do
+        emitEvent echan $ WBF.FEChange (SS "hoge")
+        hook_chan `shouldNextMatch` [(SIa, "a button"), (SIb, "b button")]
+        emitEvent echan $ WBF.FEInput SIa
+        hook_chan `shouldNextMatch` [(SIa, "a button"), (SIb, "b button")]
+        out_chan `shouldProduce` 'a'
+        gchan `shouldNowMatch` [GSet SIa, GSet SIb]
+        emitEvent echan $ WBF.FEChange (SS "")
+        hook_chan `shouldNextMatch` []
+        gchan `shouldNowMatch` [GUnset SIa, GUnset SIb]
+    it "hooks change of binding because back-end state changes" $ do
+      hook_chan <- newTChanIO
+      out_chan <- newTChanIO
+      let opt = WBE.defOption { WBE.optBindingHook = _write hook_chan  }
+          b = WBB.startFrom (SB 0)
+              $ WBB.ifBack (== (SB 0))
+              (WBB.binding' [(SIa, WBB.Action "a button" (out_chan `_write` 'a' >> State.put (SB 1)))])
+              $ WBB.whenBack (== (SB 1)) ( WBB.binding' [(SIa, WBB.Action "A BUTTON" (out_chan `_write` 'A' >> State.put (SB 0))),
+                                                         (SIc, WBB.Action "c button" (out_chan `_write` 'c'))]
+                                         )
+      withWildBind' (WBE.wildBind' opt b) $ \(EventChan echan) (GrabChan gchan) -> do
+        emitEvent echan $ WBF.FEChange (SS "")
+        hook_chan `shouldNextMatch` [(SIa, "a button")]
+        gchan `shouldNowMatch` [GSet SIa]
+        emitEvent echan $ WBF.FEInput SIa
+        out_chan `shouldProduce` 'a'
+        hook_chan `shouldNextMatch` [(SIa, "A BUTTON"), (SIc, "c button")]
+        gchan `shouldNowMatch` [GSet SIc]
+        emitEvent echan $ WBF.FEInput SIc
+        out_chan `shouldProduce` 'c'
+        hook_chan `shouldNextMatch` [(SIa, "A BUTTON"), (SIc, "c button")]
+        gchan `shouldNowMatch` []
+        emitEvent echan $ WBF.FEInput SIa
+        out_chan `shouldProduce` 'A'
+        hook_chan `shouldNextMatch` [(SIa, "a button")]
+        gchan `shouldNowMatch` [GUnset SIc]
+  describe "optCatch" $ do
+    it "receives front-state, input and exception" $ do
+      hook_chan <- newTChanIO
+      let catcher fs input err = atomically $ writeTChan hook_chan (fs, input, err)
+          opt = WBE.defOption { WBE.optCatch = catcher }
+          b = WBB.binds $ WBB.on SIa `WBB.run` (throw $ userError "BOOM!")
+      withWildBind' (WBE.wildBind' opt b) $ \(EventChan echan) _ -> do
+        emitEvent echan $ WBF.FEChange (SS "front state")
+        emitEvent echan $ WBF.FEInput SIa
+        (got_state, got_input, got_exception) <- atomically $ readTChan hook_chan
+        got_state `shouldBe` SS "front state"
+        got_input `shouldBe` SIa
+        fromException got_exception `shouldBe` Just (userError "BOOM!")
+        
diff --git a/test/WildBind/ForTest.hs b/test/WildBind/ForTest.hs
new file mode 100644
--- /dev/null
+++ b/test/WildBind/ForTest.hs
@@ -0,0 +1,30 @@
+module WildBind.ForTest
+       ( SampleInput(..),
+         SampleState(..),
+         SampleBackState(..)
+       ) where
+
+import Control.Applicative ((<$>))
+import Test.QuickCheck (Arbitrary(arbitrary,shrink), arbitraryBoundedEnum)
+
+data SampleInput = SIa | SIb | SIc
+                 deriving (Show, Eq, Ord, Enum, Bounded)
+
+instance Arbitrary SampleInput where
+  arbitrary = arbitraryBoundedEnum
+
+data SampleState = SS { unSS :: String }
+                 deriving (Show, Eq, Ord)
+
+instance Arbitrary SampleState where
+  arbitrary = SS <$> arbitrary
+  shrink (SS s) = SS <$> shrink s
+
+
+data SampleBackState = SB { unSB :: Int }
+                     deriving (Show, Eq, Ord)
+
+instance Enum SampleBackState where
+  toEnum = SB
+  fromEnum = unSB
+
diff --git a/wild-bind.cabal b/wild-bind.cabal
new file mode 100644
--- /dev/null
+++ b/wild-bind.cabal
@@ -0,0 +1,62 @@
+name:                   wild-bind
+version:                0.1.0.0
+author:                 Toshio Ito <debug.ito@gmail.com>
+maintainer:             Toshio Ito <debug.ito@gmail.com>
+license:                BSD3
+license-file:           LICENSE
+synopsis:               Dynamic key binding framework
+description:            Dynamic key binding framework. See https://github.com/debug-ito/wild-bind
+category:               UserInterface
+cabal-version:          >= 1.10
+build-type:             Simple
+extra-source-files:     README.md, ChangeLog.md
+homepage:               https://github.com/debug-ito/wild-bind
+bug-reports:            https://github.com/debug-ito/wild-bind/issues
+
+library
+  default-language:     Haskell2010
+  hs-source-dirs:       src
+  ghc-options:          -Wall -fno-warn-unused-imports
+  default-extensions:   RankNTypes OverloadedStrings
+  other-extensions:     GeneralizedNewtypeDeriving
+  exposed-modules:      WildBind,
+                        WildBind.Binding,
+                        WildBind.FrontEnd,
+                        WildBind.Description,
+                        WildBind.Exec,
+                        WildBind.Input.NumPad
+  -- other-modules:        
+  build-depends:        base >=4.6 && <5.0,
+                        text >=1.2.0 && <1.3,
+                        containers >=0.5.0 && <0.6,
+                        transformers >=0.3.0 && <0.6
+
+-- executable wild-bind
+--   default-language:     Haskell2010
+--   hs-source-dirs:       src
+--   main-is:              Main.hs
+--   ghc-options:          -Wall -fno-warn-unused-imports
+--   -- other-modules:       
+--   -- other-extensions:    
+--   build-depends:        base >=4 && <5
+
+test-suite spec
+  type:                 exitcode-stdio-1.0
+  default-language:     Haskell2010
+  hs-source-dirs:       test
+  ghc-options:          -Wall -fno-warn-unused-imports "-with-rtsopts=-M512m"
+  main-is:              Spec.hs
+  default-extensions:   OverloadedStrings FlexibleInstances MultiParamTypeClasses
+  other-extensions:     RankNTypes
+  other-modules:        WildBind.ExecSpec,
+                        WildBind.BindingSpec
+                        WildBind.ForTest
+  build-depends:        base, wild-bind, transformers,
+                        hspec >=2.1.7 && <2.3,
+                        QuickCheck >=2.6 && <3.0,
+                        stm >=2.4.2 && <2.5,
+                        microlens >=0.2.0 && <0.5
+
+source-repository head
+  type:                 git
+  location:             https://github.com/debug-ito/wild-bind.git
