diff --git a/rasa.cabal b/rasa.cabal
--- a/rasa.cabal
+++ b/rasa.cabal
@@ -1,5 +1,5 @@
 name: rasa
-version: 0.1.6
+version: 0.1.7
 cabal-version: >=1.10
 build-type: Simple
 license: MIT
diff --git a/src/Rasa.hs b/src/Rasa.hs
--- a/src/Rasa.hs
+++ b/src/Rasa.hs
@@ -17,7 +17,7 @@
 --
 -- @rasa eventProviders extensions@
 --
--- This should be imported by a user-config with and called with a 'Scheduler'
+-- This should be imported by a user-config with and called with an 'Action'
 -- containing any extensions which have event listeners.
 --
 -- > rasa $ do
diff --git a/src/Rasa/Ext.hs b/src/Rasa/Ext.hs
--- a/src/Rasa/Ext.hs
+++ b/src/Rasa/Ext.hs
@@ -14,11 +14,6 @@
 -- to editor events, or expose useful actions and/or state for other extensions
 -- to use.
 --
--- To react to events an extension defines a 'Scheduler'
--- which the user puts in their config file. The 'Scheduler'
--- defines listeners for events which the extension will react to.
--- See 'Scheduler' for more detailed information.
---
 -- Whether performing its own actions or being used by a different extension
 -- an extension will want to define some 'Action's to perform. Actions
 -- can operate over buffers or even perform IO and comprise the main way in which
@@ -30,10 +25,10 @@
 -- > logKeypress :: Keypress -> Action ()
 -- > logKeypress (Keypress char _) = liftIO $ appendFile "logs" ("You pressed " ++ [char] ++ "\n")
 -- >
--- > logger :: Scheduler ()
+-- > logger :: Action HookId
 -- > logger = do
 -- >   onInit $ liftIO $ writeFile "logs" "==Logs==\n"
--- >   eventListener logKeypress
+-- >   onEveryTrigger_ logKeypress
 -- >   onExit $ liftIO $ appendFile "logs" "==Done=="
 --
 -- Check out this tutorial on building extensions, it's also just a great way to learn
@@ -126,16 +121,26 @@
   , Hook
   , HookId
   , dispatchEvent
-  , eventListener
+  , onEveryTrigger
+  , onEveryTrigger_
+  , onNextEvent
   , removeListener
   , eventProvider
 
   -- * Built-in Event Hooks
-  , beforeEvent
-  , beforeRender
-  , onRender
-  , afterRender
   , onInit
+  , beforeEveryEvent
+  , beforeEveryEvent_
+  , beforeNextEvent
+  , beforeEveryRender
+  , beforeEveryRender_
+  , beforeNextRender
+  , onEveryRender
+  , onEveryRender_
+  , onNextRender
+  , afterEveryRender
+  , afterEveryRender_
+  , afterNextRender
   , onExit
   , onBufAdded
 
diff --git a/src/Rasa/Internal/Action.hs b/src/Rasa/Internal/Action.hs
--- a/src/Rasa/Internal/Action.hs
+++ b/src/Rasa/Internal/Action.hs
@@ -15,7 +15,7 @@
 
 
 -- | A wrapper around event listeners so they can be stored in 'Hooks'.
-data Hook = forall a. Hook HookId a
+data Hook = forall a. Hook HookId (a -> Action ())
 data HookId =
   HookId Int TypeRep
 
@@ -26,7 +26,7 @@
 type Hooks = Map TypeRep [Hook]
 
 -- | This is a monad-transformer stack for performing actions against the editor.
--- You register Actions to be run in response to events using 'Rasa.Internal.Scheduler.eventListener'
+-- You register Actions to be run in response to events using 'Rasa.Internal.Scheduler.onEveryTrigger'
 --
 -- Within an Action you can:
 --
diff --git a/src/Rasa/Internal/Scheduler.hs b/src/Rasa/Internal/Scheduler.hs
--- a/src/Rasa/Internal/Scheduler.hs
+++ b/src/Rasa/Internal/Scheduler.hs
@@ -3,16 +3,26 @@
 module Rasa.Internal.Scheduler
   ( Hook
   , Hooks
-  , afterRender
-  , beforeEvent
-  , beforeRender
+  , onEveryTrigger
+  , onEveryTrigger_
+  , onNextEvent
+  , onInit
+  , beforeEveryEvent
+  , beforeEveryEvent_
+  , beforeNextEvent
+  , beforeEveryRender
+  , beforeEveryRender_
+  , beforeNextRender
+  , onEveryRender
+  , onEveryRender_
+  , onNextRender
+  , afterEveryRender
+  , afterEveryRender_
+  , afterNextRender
   , dispatchEvent
-  , eventListener
+  , onExit
   , removeListener
   , matchingHooks
-  , onInit
-  , onExit
-  , onRender
   , onBufAdded
   ) where
 
@@ -22,6 +32,7 @@
 import Rasa.Internal.Editor
 
 import Control.Lens
+import Control.Monad
 import Data.Dynamic
 import Data.Foldable
 import Data.Map hiding (filter)
@@ -47,21 +58,34 @@
   let hookId = HookId n (typeRep (Proxy :: Proxy a))
   return (hookId, Hook hookId hookFunc)
 
+extendHook :: Hook -> Action () -> Hook
+extendHook (Hook hookId hookFunc) act = Hook hookId (\a -> hookFunc a >> act)
+
 -- | This extracts all event listener hooks from a map of hooks which match the type of the provided event.
 matchingHooks :: forall a. Typeable a => Hooks -> [a -> Action ()]
 matchingHooks hooks' = getHook <$> (hooks'^.at (typeRep (Proxy :: Proxy a))._Just)
 
 -- | This registers an event listener hook, as long as the listener is well-typed similar to this:
 --
--- @MyEventType -> Action ()@ then it will be registered to listen for dispatched events of that type.
--- Use within the 'Rasa.Internal.Scheduler.Scheduler' and add have the user add it to their config.
--- It returns an ID which may be used with 'removeListener'
-eventListener :: forall a. Typeable a => (a -> Action ()) -> Action HookId
-eventListener hookFunc = do
+-- @MyEventType -> Action ()@ then it will be triggered on all dispatched events of that type.
+-- It returns an ID which may be used with 'removeListener' to cancel the listener
+onEveryTrigger :: forall a. Typeable a => (a -> Action ()) -> Action HookId
+onEveryTrigger hookFunc = do
   (hookId, hook) <- makeHook hookFunc
   hooks %= insertWith mappend (typeRep (Proxy :: Proxy a)) [hook]
   return hookId
 
+onEveryTrigger_ :: forall a. Typeable a => (a -> Action ()) -> Action ()
+onEveryTrigger_ = void . onEveryTrigger
+
+
+-- | This acts as 'onEveryTrigger' but listens only for the first event of a given type.
+onNextEvent :: forall a. Typeable a => (a -> Action ()) -> Action ()
+onNextEvent hookFunc = do
+  (hookId, hook) <- makeHook hookFunc
+  let selfCancellingHook = extendHook hook (removeListener hookId)
+  hooks %= insertWith mappend (typeRep (Proxy :: Proxy a)) [selfCancellingHook]
+
 -- | This removes a listener and prevents it from responding to any more events.
 removeListener :: HookId -> Action ()
 removeListener hkIdA@(HookId _ typ) =
@@ -75,47 +99,71 @@
 -- Though arbitrary actions may be performed in the configuration block;
 -- it's recommended to embed such actions in the onInit event listener
 -- so that all event listeners are registered before anything Actions occur.
-onInit :: Action () -> Action HookId
-onInit action = eventListener (const action :: Init -> Action ())
+onInit :: Action () -> Action ()
+onInit action = void $ onEveryTrigger (const action :: Init -> Action ())
 
 -- | Registers an action to be performed BEFORE each event phase.
-beforeEvent :: Action () -> Action HookId
-beforeEvent action = eventListener (const action :: BeforeEvent -> Action ())
+beforeEveryEvent :: Action () -> Action HookId
+beforeEveryEvent action = onEveryTrigger (const action :: BeforeEvent -> Action ())
 
+beforeEveryEvent_ :: Action () -> Action ()
+beforeEveryEvent_ = void . beforeEveryEvent
+
+beforeNextEvent :: Action () -> Action ()
+beforeNextEvent action = onNextEvent (const action :: BeforeEvent -> Action ())
+
 -- | Registers an action to be performed BEFORE each render phase.
 --
 -- This is a good spot to add information useful to the renderer
 -- since all actions have been performed. Only cosmetic changes should
 -- occur during this phase.
-beforeRender :: Action () -> Action HookId
-beforeRender action = eventListener (const action :: BeforeRender -> Action ())
+beforeEveryRender :: Action () -> Action HookId
+beforeEveryRender action = onEveryTrigger (const action :: BeforeRender -> Action ())
 
+beforeEveryRender_ :: Action () -> Action ()
+beforeEveryRender_ = void . beforeEveryRender
+
+beforeNextRender :: Action () -> Action ()
+beforeNextRender action = onNextEvent (const action :: BeforeRender -> Action ())
+
 -- | Registers an action to be performed during each render phase.
 --
 -- This phase should only be used by extensions which actually render something.
-onRender :: Action () -> Action HookId
-onRender action = eventListener (const action :: OnRender -> Action ())
+onEveryRender :: Action () -> Action HookId
+onEveryRender action = onEveryTrigger (const action :: OnRender -> Action ())
 
+onEveryRender_ :: Action () -> Action ()
+onEveryRender_ = void . onEveryRender
+
+onNextRender :: Action () -> Action ()
+onNextRender action = onNextEvent (const action :: OnRender -> Action ())
+
 -- | Registers an action to be performed AFTER each render phase.
 --
 -- This is useful for cleaning up extension state that was registered for the
 -- renderer, but needs to be cleared before the next iteration.
-afterRender :: Action () -> Action HookId
-afterRender action = eventListener (const action :: AfterRender -> Action ())
+afterEveryRender :: Action () -> Action HookId
+afterEveryRender action = onEveryTrigger (const action :: AfterRender -> Action ())
 
+afterEveryRender_ :: Action () -> Action ()
+afterEveryRender_ = void . afterEveryRender
+
+afterNextRender :: Action () -> Action ()
+afterNextRender action = onNextEvent (const action :: AfterRender -> Action ())
+
 -- | Registers an action to be performed during the exit phase.
 --
 -- This is only triggered exactly once when the editor is shutting down. It
 -- allows an opportunity to do clean-up, kill any processes you've started, or
 -- save any data before the editor terminates.
 
-onExit :: Action () -> Action HookId
-onExit action = eventListener (const action :: Exit -> Action ())
+onExit :: Action () -> Action ()
+onExit action = void $ onEveryTrigger (const action :: Exit -> Action ())
 
 -- | Registers an action to be performed after a new buffer is added.
 --
 -- The supplied function will be called with a 'BufRef' to the new buffer, and the resulting 'Action' will be run.
 onBufAdded :: (BufRef -> Action ()) -> Action HookId
-onBufAdded f = eventListener listener
+onBufAdded f = onEveryTrigger listener
   where
     listener (BufAdded bRef) = f bRef
