diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for tasty-test
+
+## 0.1.0.0 -- 2023-08-07
+
+* Release of first version on Hackage
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+BSD 3-Clause License
+
+Copyright (c) 2023, David Binder
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the copyright holder nor the names of its
+   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 HOLDER 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,32 @@
+# tasty-coverage
+
+A [tasty](https://hackage.haskell.org/package/tasty) ingredient which allows to generate per-test coverage data.
+
+If the GHC compiler is passed the `-fhpc` flag, then the generated code is instrumented in order to also emit information about the executed parts of the sourcecode at runtime.
+This coverage information is written to a file with the suffix `.tix`.
+For testsuites it is sometimes more useful to have the coverage information for each test individually.
+This information can be collected using the methods from the `Trace.Hpc.Reflect` module from the [hpc](https://hackage.haskell.org/package/hpc) library.
+The `tasty-coverage` package provides a simple ingredient for the [tasty](https://hackage.haskell.org/package/tasty) testsuite driver which allows to run the testsuite with the `--report-coverage` option.
+When this option is passed, one `.tix` file is generated for each individual test.
+Passing tests have the file suffix `PASSED.tix`, whereas failing tests have the suffix `FAILED.tix`.
+
+```console
+> cabal run tasty-coverage-test -- --help
+Mmm... tasty test suite
+
+Usage: tasty-coverage-test [-p|--pattern PATTERN] [-t|--timeout DURATION] 
+                           [--report-coverage]
+
+Available options:
+  -h,--help                Show this help text
+  -p,--pattern PATTERN     Select only tests which satisfy a pattern or awk
+                           expression
+  -t,--timeout DURATION    Timeout for individual tests (suffixes: ms,s,m,h;
+                           default: s)
+  --report-coverage        Generate per-test coverage data
+
+> cabal run tasty-coverage-test -- --report-coverage
+Wrote coverage file: tix/UnitTests.testOne.PASSED.tix
+Wrote coverage file: tix/UnitTests.testTwo.PASSED.tix
+Wrote coverage file: tix/UnitTests.testThree.FAILED.tix
+```
diff --git a/src/Test/Tasty/CoverageReporter.hs b/src/Test/Tasty/CoverageReporter.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/Tasty/CoverageReporter.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE InstanceSigs #-}
+module Test.Tasty.CoverageReporter (coverageReporter) where
+
+import Test.Tasty
+import Test.Tasty.Ingredients
+import Test.Tasty.Options
+import Test.Tasty.Runners
+import Test.Tasty.Providers
+import Data.Typeable
+import Trace.Hpc.Reflect ( clearTix, examineTix )
+import Trace.Hpc.Tix ( writeTix )
+import System.FilePath ( (<.>), (</>) )
+import Control.Monad (forM_)
+import qualified Data.List.NonEmpty as NE
+import Data.List.NonEmpty ( NonEmpty )
+import Data.Foldable (fold)
+import Data.Bifunctor (first)
+
+newtype ReportCoverage = MkReportCoverage   Bool
+  deriving (Eq, Ord, Typeable)
+
+instance IsOption ReportCoverage where
+    defaultValue  = MkReportCoverage False
+    parseValue = fmap MkReportCoverage . safeReadBool
+    optionName = pure "report-coverage"
+    optionHelp = pure "Generate per-test coverage data"
+    optionCLParser = mkFlagCLParser mempty (MkReportCoverage True)
+
+
+tixDir :: FilePath
+tixDir = "tix"
+
+-- | Obtain the list of all tests in the suite
+testNames :: OptionSet -> TestTree -> IO ()
+testNames  os tree = forM_ (foldTestTree coverageFold os tree) $ \(s,f) -> f (fold (NE.intersperse "." s))
+
+
+
+-- | Collect all tests and
+coverageFold :: TreeFold [(NonEmpty TestName, String -> IO ())]
+coverageFold = trivialFold
+       { foldSingle = \opts name test -> do
+          let f n = do
+                -- Collect the coverage data for exactly this test.
+                clearTix
+                result <- run opts test (\_ -> pure ())
+                tix <- examineTix
+                let filepath = tixFilePath n result
+                writeTix filepath tix
+                putStrLn ("Wrote coverage file: " <> filepath)
+          pure (NE.singleton name, f),
+          -- Append the name of the testgroup to the list of TestNames
+          foldGroup = \_ groupName acc -> fmap (first (NE.cons groupName)) acc
+        }
+
+tixFilePath :: TestName -> Result -> FilePath
+tixFilePath tn Result { resultOutcome = Success }  = tixDir </> tn <.> "PASSED" <.> ".tix"
+tixFilePath tn Result { resultOutcome = Failure _ } = tixDir </> tn <.> "FAILED" <.> ".tix"
+
+coverageReporter :: Ingredient
+coverageReporter = TestManager coverageOptions coverageRunner
+
+coverageOptions :: [OptionDescription]
+coverageOptions = [Option (Proxy :: Proxy ReportCoverage)]
+
+coverageRunner :: OptionSet -> TestTree -> Maybe (IO Bool)
+coverageRunner opts tree = case lookupOption opts of
+  MkReportCoverage False -> Nothing
+  MkReportCoverage True -> Just $ do
+    testNames opts tree
+    pure True
+
+  
diff --git a/tasty-coverage.cabal b/tasty-coverage.cabal
new file mode 100644
--- /dev/null
+++ b/tasty-coverage.cabal
@@ -0,0 +1,39 @@
+cabal-version:   3.0
+name:            tasty-coverage
+version:         0.1.0.0
+license:         BSD-3-Clause
+license-file:    LICENSE
+copyright:       David Binder, 2023
+maintainer:      david.binder@uni-tuebingen.de
+author:          David Binder
+tested-with:     ghc ==9.2.7 || ==9.4.5 || ==9.6.2
+homepage:        https://github.com/BinderDavid/tasty-coverage
+bug-reports:     https://github.com/BinderDavid/tasty-coverage/issues
+synopsis:
+    Ingredient for tasty which generates per-test coverage reports
+
+description:
+    An ingredient for the tasty testing framework which allows to generate per-test coverage reports.
+    For every test "foo" a file "foo.PASSED.tix" or "foo.FAILED.tix" is generated, depending on whether the test passed or failed. 
+
+category:        Testing
+build-type:      Simple
+extra-doc-files:
+    CHANGELOG.md
+    README.md
+
+source-repository head
+    type:     git
+    location: git@github.com:BinderDavid/tasty-coverage.git
+
+library
+    exposed-modules:  Test.Tasty.CoverageReporter
+    hs-source-dirs:   src
+    default-language: Haskell2010
+    ghc-options:      -Wall
+    build-depends:
+        base >=4.16 && <4.20,
+        tasty ^>=1.4,
+        hpc >=0.6 && <0.8,
+        filepath >=1.3.8 && <1.4.100
+
