diff --git a/exec/main.hs b/exec/main.hs
--- a/exec/main.hs
+++ b/exec/main.hs
@@ -1,6 +1,7 @@
 import Halive
 import Banner
 import System.Environment
+import Control.Applicative
 
 separateArgs :: [String] -> ([String], [String])
 separateArgs args = (haliveArgs, drop 1 targetArgs)
diff --git a/halive.cabal b/halive.cabal
--- a/halive.cabal
+++ b/halive.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                halive
-version:             0.1.0.3
+version:             0.1.0.4
 synopsis:            A live recompiler
 description:         
   Live recompiler for Haskell
@@ -33,11 +33,13 @@
   hs-source-dirs:      src
   exposed-modules:
     Halive.Utils
+    Halive.Concurrent
   default-language:    Haskell2010
   ghc-options:         -Wall
   build-depends:
     base,
-    foreign-store
+    foreign-store,
+    containers
   
 
 executable halive
diff --git a/src/Halive/Concurrent.hs b/src/Halive/Concurrent.hs
new file mode 100644
--- /dev/null
+++ b/src/Halive/Concurrent.hs
@@ -0,0 +1,47 @@
+module Halive.Concurrent (
+  killThreads,
+  registerThread,
+  forkIO',
+  forkOS'
+  ) where
+
+import Control.Concurrent
+import System.IO.Unsafe
+import           Data.Set (Set)
+import qualified Data.Set as Set
+
+-- | A small collection of helper functions for creating threads that can be killed each time Halive re-runs your main function.
+-- This is helpful for programs where you control the threads, but doesn't solve the problem of libraries that use threads 
+-- (unless you unpack them and replace all forkIO/forkOS with forkIO'/forkOS')
+-- It would be good to ask GHC devs about this; 
+-- perhaps a GHC flag that registers threads similar to this module, for development use only?
+
+-- An internal global variable to hold threads that should be killed
+{-# NOINLINE registeredThreads #-}
+registeredThreads :: MVar (Set ThreadId)
+registeredThreads = unsafePerformIO (newMVar Set.empty)
+
+-- | Kill all threads registered to be killed.
+-- Meant to be called at the beginning of your program to clean up threads from the last execution before continuing
+killThreads :: IO ()
+killThreads = modifyMVar_ registeredThreads $ \threadIDs -> do
+  mapM_ killThread threadIDs
+  return Set.empty
+
+-- | Register a thread to be killed when killThreads is called
+registerThread :: ThreadId -> IO ()
+registerThread threadID = modifyMVar_ registeredThreads (return . Set.insert threadID)
+
+-- | Fork a thread and register it to be killed when killThreads is called
+forkIO' :: IO () -> IO ThreadId
+forkIO' action = do
+  threadID <- forkIO action
+  registerThread threadID
+  return threadID
+
+-- | Fork an OS thread and register it to be killed when killThreads is called
+forkOS' :: IO () -> IO ThreadId
+forkOS' action = do
+  threadID <- forkOS action
+  registerThread threadID
+  return threadID
