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/chell-quickcheck.cabal b/chell-quickcheck.cabal
new file mode 100644
--- /dev/null
+++ b/chell-quickcheck.cabal
@@ -0,0 +1,30 @@
+name: chell-quickcheck
+version: 0.1
+synopsis: Quiet test runner (QuickCheck support)
+license: MIT
+license-file: license.txt
+author: John Millikin <jmillikin@gmail.com>
+build-type: Simple
+cabal-version: >= 1.6
+category: Testing
+bug-reports: mailto:jmillikin@gmail.com
+homepage: https://john-millikin.com/software/chell/
+tested-with: GHC==6.12.1
+
+source-repository head
+  type: bazaar
+  location: https://john-millikin.com/software/chell/
+
+library
+  ghc-options: -Wall
+  hs-source-dirs: src
+
+  build-depends:
+      base >= 4 && < 5
+    , chell >= 0.1 && < 0.2
+    , QuickCheck >= 2.3 && < 2.5
+    , random
+    , text
+
+  exposed-modules:
+    Test.Chell.QuickCheck
diff --git a/license.txt b/license.txt
new file mode 100644
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2011 John Millikin
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/Test/Chell/QuickCheck.hs b/src/Test/Chell/QuickCheck.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/Chell/QuickCheck.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Test.Chell.QuickCheck
+	( property
+	) where
+
+import           Data.Text (Text, pack)
+
+import           System.Random (mkStdGen)
+import qualified Test.Chell as Chell
+import qualified Test.QuickCheck as QuickCheck
+import qualified Test.QuickCheck.Gen as Gen
+import qualified Test.QuickCheck.State as State
+import qualified Test.QuickCheck.Test as Test
+import qualified Test.QuickCheck.Text as Text
+
+-- | Convert a QuickCheck property to a Chell 'Chell.Suite'.
+--
+-- @
+--import Test.Chell
+--import Test.Chell.QuickCheck
+--import Test.QuickCheck hiding (property)
+--
+--tests :: [Suite]
+--tests =
+--    [ suite \"foo\"
+--        [ property \"bar\" (\xs -> not (null xs) ==> length xs > 0)
+--        ]
+--    ]
+-- @
+property :: QuickCheck.Testable prop => Text -> prop -> Chell.Suite
+property name prop = Chell.test (Chell.Test name chell_io) where
+	chell_io opts = do
+		let seed = Chell.testOptionSeed opts
+		
+		term <- Text.newNullTerminal
+		
+		let args = QuickCheck.stdArgs
+		let state = State.MkState
+			{ State.terminal = term
+			, State.maxSuccessTests = QuickCheck.maxSuccess args
+			, State.maxDiscardedTests = QuickCheck.maxDiscard args
+			, State.computeSize = computeSize
+			  	(QuickCheck.maxSize args)
+			  	(QuickCheck.maxSuccess args)
+			, State.numSuccessTests = 0
+			, State.numDiscardedTests = 0
+			, State.collected = []
+			, State.expectedFailure = False
+			, State.randomSeed = mkStdGen seed
+			, State.numSuccessShrinks = 0
+			, State.numTryShrinks = 0
+			}
+		
+		result <- Test.test state (Gen.unGen (QuickCheck.property prop))
+		let output = pack (Test.output result)
+		return $ case result of
+			Test.Success{} -> Chell.TestPassed
+				[("seed", pack (show seed))]
+			Test.Failure{} -> Chell.TestFailed
+				[("seed", pack (show seed))]
+				[Chell.Failure Nothing output]
+			Test.GaveUp{} -> Chell.TestAborted
+				[("seed", pack (show seed))]
+				output
+			Test.NoExpectedFailure{} -> Chell.TestFailed
+				[("seed", pack (show seed))]
+				[Chell.Failure Nothing output]
+
+-- copied from quickcheck-2.4.1.1/src/Test/QuickCheck/Test.hs
+computeSize :: Int -> Int -> Int -> Int -> Int
+computeSize maxSize maxSuccess n d
+	-- e.g. with maxSuccess = 250, maxSize = 100, goes like this:
+	-- 0, 1, 2, ..., 99, 0, 1, 2, ..., 99, 0, 2, 4, ..., 98.
+	| n `roundTo` maxSize + maxSize <= maxSuccess ||
+	  n >= maxSuccess ||
+	  maxSuccess `mod` maxSize == 0 = n `mod` maxSize + d `div` 10
+	| otherwise =
+	 (n `mod` maxSize) * maxSize `div` (maxSuccess `mod` maxSize) + d `div` 10
+
+roundTo :: Int -> Int -> Int
+roundTo n m = (n `div` m) * m
