diff --git a/README b/README
--- a/README
+++ b/README
@@ -1,12 +1,4 @@
-project-foo [1] is a template for a package, to make it easy to copy &
-modify.  It uses cabal-make [2] for convenience.  It's even equipped with
-a darcs repo.  Copy the directory ("cp -rp"), "darcs mv" the .cabal file,
-edit README and wikipage.tw.  Then "darcs update" the changes and add new
-content with "make check-add" and "make add-new".  When ready, do a "darcs
-put" or "make repo".
-
-Please share any comments & suggestions on the discussion (talk) page at
-[1].
+reactive-glut [1] connects the Reactive [2] and GLUT [3] packages.
 
 You can configure, build, and install all in the usual way with Cabal
 commands.
@@ -17,5 +9,6 @@
 
 References:
 
-[1] http://haskell.org/haskellwiki/project-foo
-[1] http://haskell.org/haskellwiki/cabal-make
+[1] http://haskell.org/haskellwiki/reactive-glut
+[2] http://haskell.org/haskellwiki/reactive
+[3] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/GLUT
diff --git a/reactive-glut.cabal b/reactive-glut.cabal
--- a/reactive-glut.cabal
+++ b/reactive-glut.cabal
@@ -1,5 +1,5 @@
 Name:                reactive-glut
-Version:             0.0.4
+Version:             0.1.0
 Cabal-Version:       >= 1.2
 Synopsis:            Connects Reactive and GLUT
 Category:            FRP, graphics
@@ -8,9 +8,6 @@
   FRP library \"Reactive\".
   .
   Project wiki page: <http://haskell.org/haskellwiki/reactive-glut>
-  .
-  The module documentation pages have links to colorized source code and
-  to wiki pages where you can read and contribute user comments.  Enjoy!
   .
   &#169; 2008 by Conal Elliott; BSD3 license.
 Author:              Conal Elliott 
diff --git a/src/FRP/Reactive/GLUT/Adapter.hs b/src/FRP/Reactive/GLUT/Adapter.hs
--- a/src/FRP/Reactive/GLUT/Adapter.hs
+++ b/src/FRP/Reactive/GLUT/Adapter.hs
@@ -40,11 +40,11 @@
 adapt f =
   do clock <- makeClock
      let mkE = makeEvent clock
-     (mousePosE, mousePosSink ) <- mkE
-     (leftDown , leftDownSink ) <- mkE
-     (rightDown, rightDownSink) <- mkE
-     (keyPress , keyPressSink ) <- mkE
-     (tick     , tickSink     ) <- mkE
+     (mousePosE , mousePosSink ) <- mkE
+     (leftDown  , leftDownSink ) <- mkE
+     (rightDown , rightDownSink) <- mkE
+     (keyActions, keyActionSink) <- mkE
+     (tick      , tickSink     ) <- mkE
      -- TODO: let the initial mouse position be its actual position
      let windowPoint' p = do -- putStrLn $ "window point " ++ show p
                              windowPoint p
@@ -61,13 +61,15 @@
        case (k,ks) of
          (G.MouseButton G.LeftButton ,G.Down) -> leftDownSink  ()
          (G.MouseButton G.RightButton,G.Down) -> rightDownSink ()
-         (G.Char c      ,G.Down) -> keyPressSink (Char c)
-         (G.SpecialKey s,G.Down) -> keyPressSink (SpecialKey s)
+         (G.Char c      ,G.Down) -> keyActionSink ((Down, Char c))
+         (G.SpecialKey s,G.Down) -> keyActionSink ((Down, SpecialKey s))
+         (G.Char c      ,G.Up) -> keyActionSink ((Up, Char c))
+         (G.SpecialKey s,G.Up) -> keyActionSink ((Up, SpecialKey s))
          _ -> return ()
       )
      updater <- mkUpdater
                  (cGetTime clock)
-                 (glwrap <$> f (UI mousePos leftDown rightDown keyPress tick))
+                 (glwrap <$> f (UI mousePos leftDown rightDown keyActions tick))
      schedule (updater >> tickSink ())
      -- putStrLn "mainLoop"
      G.mainLoop
diff --git a/src/FRP/Reactive/GLUT/SimpleGL.hs b/src/FRP/Reactive/GLUT/SimpleGL.hs
--- a/src/FRP/Reactive/GLUT/SimpleGL.hs
+++ b/src/FRP/Reactive/GLUT/SimpleGL.hs
@@ -92,8 +92,13 @@
      -- colorMaterial $= Just (FrontAndBack,Specular)
 
      reshapeCallback     $= Just resizeScene
+
+     -- The next line allows a graceful exit, e.g., back into ghci.
+     -- However, it relies on freeglut.  If you have (non-free) GLUT,
+     -- comment it out.  I'd like to make the check at runtime, but I
+     -- don't know how.  Help, please.
      actionOnWindowClose $= MainLoopReturns
-     -- loadIdentity
+
 
 
 -- | Convert a window position to a logical X,Y.  Logical zero is at the
diff --git a/src/FRP/Reactive/GLUT/UI.hs b/src/FRP/Reactive/GLUT/UI.hs
--- a/src/FRP/Reactive/GLUT/UI.hs
+++ b/src/FRP/Reactive/GLUT/UI.hs
@@ -16,12 +16,13 @@
 
 module FRP.Reactive.GLUT.UI
   ( UI(..)
-  , Key(..), SpecialKey(..)
+  , KeyState(..), Key(..), G.SpecialKey(..)
+  , keyPressed
   , uiIntegral
   ) where
 
 import Control.Applicative (liftA2)
-import Graphics.UI.GLUT(SpecialKey(..))
+import qualified Graphics.UI.GLUT as G
 
 import Data.VectorSpace
 import FRP.Reactive
@@ -31,12 +32,21 @@
   mousePosition      :: Behavior (Double,Double),
   leftButtonPressed  :: Event (),
   rightButtonPressed :: Event (),
-  keyPressed         :: Event Key,
+  keyAction          :: Event (KeyState, Key),
   framePass          :: Event ()
 }
 
+-- TODO: make button and key interfaces alike
+
 -- | Key pressed
-data Key = Char Char | SpecialKey SpecialKey
+data Key = Char Char | SpecialKey G.SpecialKey
+    deriving (Eq, Ord, Show)
+data KeyState = Down | Up
+    deriving (Eq, Ord, Show)
+
+-- | Key press events.
+keyPressed :: UI -> Event Key
+keyPressed = fmap snd . filterE ((==Down) . fst) . keyAction
 
 -- | Integral tracking frame sampling
 uiIntegral :: (VectorSpace v, Scalar v ~ TimeT) =>
diff --git a/wikipage.tw b/wikipage.tw
--- a/wikipage.tw
+++ b/wikipage.tw
@@ -1,6 +1,7 @@
 [[Category:Packages]]
 [[Category:FRP]]
 [[Category:Graphics]]
+[[Category:3D]]
 
 == Abstract ==
 
@@ -8,12 +9,10 @@
 It also serves as a demonstration for how to hook up imperative (i.e., legacy) libraries [[Reactive]].
 For a functional alternative to OpenGL/GLUT and reactive-glut, see [[FieldTrip]] and [[reactive-fieldtrip]].
 
-'''Note:''' The repo has moved from <code>conal.net</code> to <code>code.haskell.org</code>.
-
 Besides this wiki page, here are more ways to find out about reactive-glut:
-* Read [http://code.haskell.org/reactive-glut/doc/html/ the library documentation].
-* Get the code repository: '''<tt>darcs get http://code.haskell.org/reactive-glut</tt>'''.
-* Install from [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/reactive-glut Hackage].
-* See the [[reactive-glut/Versions| version history]].
+* Visit the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/reactive-glut Hackage page] for library documentation and to download & install.
+* Or install with <tt>cabal install reactive-glut</tt>.
+* Get the code repository: <tt>darcs get http://code.haskell.org/reactive-glut</tt>.
+<!-- * See the [[reactive-glut/Versions| version history]]. -->
 
 Please leave comments at the [[Talk:reactive-glut|Talk page]].
